Java - регулярное выражение для разделения токенов с минимальным размером и разделителями

1

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

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

  • Разделители являются [.?!] (конец предложения)
  • Десятичные числа не должны быть символизированы
  • Разделители не следует удалять.
  • Минимальный размер каждого токена должен быть 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. в качестве отдельного предложения.

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

ОБНОВЛЕНИЕ:. Как Chris, упомянутых в комментариях, почти невозможно решить такие вопросы (чтобы охватить все случаи происходят на естественных языках) с регулярным выражением. Тем не менее, я нашел HamZa ответом на шкаф и самый полезный.

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

  • 0
    Мы уверены, что в конце каждого предложения есть пробел?
  • 0
    И что произойдет, если предложение короче, чем 5 символов, т. Hey! ?
Показать ещё 14 комментариев
Теги:
split
delimiter

2 ответа

2
Лучший ответ

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

Теперь измените его на нужды этого вопроса:

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

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

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

  • 2
    Это не сработает, если аббревиатура на самом деле находится в конце предложения, например, I live in the USA We speak English. Кроме того, он все еще разделен на сокращения только одной части, например, Employees at Grammar Inc. make pedantic comments on the internet. Оба из них по существу неразрешимы с RegEx.
  • 0
    @ChrisBode Да, я знаю.
2

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

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

например.

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
    Технически, это правильный ответ, но я предпочитаю ответ Хамзы, который не разделяет "США" и "доллар" Спасибо, приятель

Ещё вопросы

Сообщество Overcoder
Наверх
Меню