Включить точку в предложении - регулярное выражение
У меня 40 000 строк, и мне нужно разделить каждую строку на разные предложения. Теперь я использую шаблон так:
String patternStr2 = "\\s*[\"']?\\s*([A-Z0-9].*?[\\.\\?!]\\s)['\"]?\\s*";
Он может обрабатывать почти все предложения, но для таких предложений: ВМС США, Первая мировая война будет разделена на 2 части: США и ВМС, Первая мировая война.
Есть ли решение для решения этой проблемы?
3 ответа
String patternStr2 = "(?<!\\..)(?<![A-Z].)[\\.\\?!](?!.\\.)
"; затем с помощью метода java Matcher find() можно получить все предложения.
Почему вы пытаетесь соответствовать, пока вы хотите разделить?
Используйте следующее регулярное выражение:
(?<!\..)\.(?!.\.)
Объяснение:
(?<!\..)
: Отрицательный взгляд за спиной, проверьте, нет ли сзади 2 символов.\.
: Сопоставить точку.(?!.\.)
: Отрицательный взгляд вперед, проверьте, нет ли впереди 2 символов.
Примечание: не уверен, как это сделать в JAVA, но я думаю, что вы должны попробовать (?<!\\..)\\.(?!.\\.)
, Также не забудьте добавить точку к вашим расщепленным предложениям.
Хорошо, я думаю, что вы не должны использовать регулярные выражения для этого, но я не мог удержаться от добавления некоторых.
Если это трудно понять, дайте мне знать, и я добавлю несколько комментариев...
package test;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
private static final Pattern SENTENCE_DELIMITER =
Pattern.compile("((.+?)((?<!\\.[A-Z])(\\.\\s)(.+))?)");
public static void main(String[] args) {
String lineWithOneSentence =
"U.S. Navy, World War I";
String lineWithTwoSentences =
"U.S. Navy, World War I. U.S. Air Force, World War III.";
Matcher matcher = SENTENCE_DELIMITER.matcher(lineWithOneSentence);
if (matcher.matches()) {
for (int i = 0; i <= matcher.groupCount(); i++) {
switch (i) {
case 0:
System.out.println("WHOLE MATCH: " + matcher.group(i));
break;
case 2:
System.out.println("FIRST SENTENCE: "+ matcher.group(i));
break;
case 5:
System.out.println("SECOND SENTENCE: " + matcher.group(i));
default:
}
}
}
matcher = SENTENCE_DELIMITER.matcher(lineWithTwoSentences);
if (matcher.matches()) {
for (int i = 0; i <= matcher.groupCount(); i++) {
switch (i) {
case 0:
System.out.println("WHOLE MATCH: " + matcher.group(i));
break;
case 2:
System.out.println("FIRST SENTENCE: "+ matcher.group(i));
break;
case 5:
System.out.println("SECOND SENTENCE: " + matcher.group(i));
default:
}
}
}
}
}
Обходной путь здесь заключается в следующем:
- Используйте группы
- Используйте отрицательный вид сзади для точек, за которыми следует пробел, чтобы убедиться, что им не предшествует точка, за которой следует заглавная буква (как в "U *.S*._").
Это довольно излишне и, вероятно, будет проблемой в какой-то момент, например, если ваш текст не является последовательным в соответствии с пунктуацией.
Ouput:
WHOLE MATCH: U.S. Navy, World War I
FIRST SENTENCE: U.S. Navy, World War I
SECOND SENTENCE: null
WHOLE MATCH: U.S. Navy, World War I. U.S. Air Force, World War III.
FIRST SENTENCE: U.S. Navy, World War I
SECOND SENTENCE: U.S. Air Force, World War III.