2013-08-16 2 views
1

Я знаю, что знаю, есть много похожих вопросов, и я могу сказать, что я прочитал их все. Но я не очень хорошо разбираюсь в регулярном выражении, и я не мог понять, какое регулярное выражение мне нужно.Java - регулярное выражение для разделения токенов с минимальным размером и разделителями

Я хочу, чтобы разбить строку в Java, и у меня есть 4 ограничения:

  1. Разделители являются (конец предложения)
  2. Десятичные числа не должны быть лексического
  3. [.?!]
  4. Разделители не следует удалять.
  5. Минимальный размер каждого маркера должно быть 5

Например, для ввода:

"Hello World! This answer worth $1.45 in U.S. dollar. Thank you."

Выходной сигнал будет:

[Hello World!, This answer worth $1.45 in U.S. dollar., Thank you.]

До сих пор Я получил ответ для трех первых ограничений этого регулярного выражения:

text.split("(?<=[.!?])(?<!\\d)(?!\\d)"); 

И я знаю, что должен использовать {5,} где-то в моем регулярном выражении, но любая комбинация, которую я пробовал, не работает.

Для таких случаев, как: "I love U.S. How about you?" Не имеет значения, дает ли оно мне одно или два предложения, поскольку оно не делает токенизацию S. в виде отдельной фразы.

И, наконец, знакомство с хорошим руководством по регулярному выражению оценивается.

UPDATE: Как Chris упоминалось в комментариях, практически невозможно решить такие вопросы, как это (чтобы охватить все случаи происходят в естественных языках) с регулярным выражением. Однако я нашел ответ Хамза в шкафу и самый полезный.

Итак, будьте осторожны! Принятый ответ не будет охватывать все возможные варианты использования!

+0

Мы уверены, что в конце каждого предложения есть пробел? – Juto

+0

И что произойдет, если предложение короче 5 символов, т. Е. «Эй!»? – Juto

+0

@ Juto Это может быть. В этом примере есть пробелы, но не во всех случаях. –

ответ

2

Основание моего ответа от previously made regex.
Регулярное выражение было в основном (?<=[.?!])\s+(?=[a-z]), что означает соответствие любой пробел один или несколько раз предшествует либо ., ? или ! и последующим [a-z] (не забывая при этом модификатор i).

Теперь давайте изменим его к потребностям этого вопроса:

  1. Мы сначала преобразовать его в JAVA регулярное выражение: (?<=[.?!])\\s+(?=[a-z])
  2. Мы добавим модификатор i, чтобы соответствовать нечувствительно к регистру (?i)(?<=[.?!])\\s+(?=[a-z])
  3. Мы положим выражение в позитивном свете, чтобы предотвратить «поедание» символов (в этом случае разделители): (?=(?i)(?<=[.?!])\\s+(?=[a-z]))
  4. Мы добавим отрицательный lookbehind, чтобы проверить, нет ли аббревиатуры ции в формате LETTER DOT LETTER DOT: (?i)(?<=[.?!])(?<![a-z]\.[a-z]\.)\\s+(?=[a-z])

Таким образом, наше окончательное регулярное выражение выглядит следующим образом: (?i)(?<=[.?!])(?<![a-z]\.[a-z]\.)\\s+(?=[a-z]).

Некоторые ссылки:

+2

Это не удается, если аббревиатура фактически находится в конце предложения, например. «Я живу в США. Мы говорим по-английски». Кроме того, он по-прежнему расщепляется на аббревиатуры только одной части, например. «Сотрудники Grammar Inc. делают педантичные комментарии в Интернете». Оба они по существу неразрешимы с RegEx. –

+0

@ChrisBode Yup, я знаю. – HamZa

2

Как насчет следующего регулярного выражения?

(?<=[.!?])(?!\w{1,5})(?<!\d)(?!\d) 

e.g.

private static final Pattern REGEX_PATTERN = 
     Pattern.compile("(?<=[.!?])(?!\\w{1,5})(?<!\\d)(?!\\d)"); 

public static void main(String[] args) { 
    String input = "Hello World! This answer worth $1.45 in U.S. dollar. Thank you."; 

    System.out.println(java.util.Arrays.toString(
     REGEX_PATTERN.split(input) 
    )); // prints "[Hello World!, This answer worth $1.45 in U.S., dollar., Thank you.]" 
} 
+0

Технически, это правильный ответ, но я предпочитаю ответ Хамзы, который не разделяет «U.S.», и «доллар» Спасибо, приятель –

Смежные вопросы