Java - регулярное выражение для разделения токенов с минимальным размером и разделителями
Я знаю, я знаю, есть много похожих вопросов, и я могу сказать, что я прочитал все из них. Но я не очень хорош в регулярных выражениях, и я не мог понять, какое регулярное выражение мне нужно.
Я хочу разделить строку в 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 Bode в комментариях, почти невозможно решить подобные вопросы (чтобы охватить все случаи, происходящие на естественных языках) с помощью регулярных выражений. Тем не менее, я нашел ответ HamZa шкафу, и самый полезный.
Так что будьте осторожны! Принятый ответ не охватывает все возможные варианты использования!
2 ответа
Основываясь на моем ответе из ранее сделанного регулярного выражения.
Регулярное выражение было в основном (?<=[.?!])\s+(?=[a-z])
что означает совпадение с любым пробелом один или несколько раз, которому предшествует либо .
, ?
или же !
и затем [a-z]
(не забывая i
модификатор).
Теперь давайте изменим это в соответствии с потребностями этого вопроса:
- Сначала мы преобразуем его в регулярное выражение JAVA:
(?<=[.?!])\\s+(?=[a-z])
- Мы добавим
i
модификатор для соответствия без учета регистра(?i)(?<=[.?!])\\s+(?=[a-z])
- Мы положим выражение в позитивную перспективу, чтобы не "съесть" символы (в данном случае разделители):
(?=(?i)(?<=[.?!])\\s+(?=[a-z]))
- Мы добавим отрицательный вид сзади, чтобы проверить, нет ли сокращения в формате
LETTER DOT LETTER DOT
:(?i)(?<=[.?!])(?<![a-z]\.[a-z]\.)\\s+(?=[a-z])
Итак, наше последнее выражение выглядит так: (?i)(?<=[.?!])(?<![a-z]\.[a-z]\.)\\s+(?=[a-z])
,
Некоторые ссылки:
- Онлайн тестер, переход на JAVA
- Инструмент объяснения (не на основе JAVA)
- Учебник по регулярным выражениям
- Учебник по регулярным выражениям Java
- ТАК регулярное выражение чата
- Некоторые продвинутые хорошие регулярные выражения на SO
- Как это регулярное выражение находит треугольные числа?
- Как мы можем сопоставить ^n b^n с регулярным выражением Java?
- Как это регулярное выражение Java обнаруживает палиндромы?
- Как определить, является ли число простым с регулярным выражением?
- "вертикальное" сопоставление регулярных выражений в "изображении" ASCII
- Можно ли исключить цикл for из этого фрагмента кода PHP?
^ - См. Решение регулярных выражений, хотя не уверен, если это применимо в JAVA
Как насчет следующего регулярного выражения?
(?<=[.!?])(?!\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.]"
}