我有40,000行,需要将每行分成不同的句子。现在,我使用的模式是这样的:在句子中加入句子 - 正则表达式
String patternStr2 = "\\s*[\"']?\\s*([A-Z0-9].*?[\\.\\?!]\\s)['\"]?\\s*";
它可以处理几乎所有的句子,但像这样的句子: 美国海军,第一次世界大战 将被分为2个部分:美国和海军,第一次世界大战
有没有解决方案来解决这个问题?
我有40,000行,需要将每行分成不同的句子。现在,我使用的模式是这样的:在句子中加入句子 - 正则表达式
String patternStr2 = "\\s*[\"']?\\s*([A-Z0-9].*?[\\.\\?!]\\s)['\"]?\\s*";
它可以处理几乎所有的句子,但像这样的句子: 美国海军,第一次世界大战 将被分为2个部分:美国和海军,第一次世界大战
有没有解决方案来解决这个问题?
String patternStr2 =“(?<!\\..)(?<![A-Z].)[\\.\\?!](?!.\\.)
”;然后通过使用java Matcher find()方法,可以得到所有的句子。
好吧我认为你应该不是使用正则表达式,但我无法拒绝投入一些。
如果这是很难理解,让我知道,我会添加一些评论...
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:
}
}
}
}
}
这里的解决方法是:
这相当矫枉过正,可能会在某个时候出现问题,即如果您的文本不符合标点符号。
输出继电器:
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.
为什么你想比赛同时要分裂?
使用以下正则表达式:
(?<!\..)\.(?!.\.)
说明:
(?<!\..)
:负回顾后,检查是否没有一点后面2个字符。
\.
:匹配一个点。
(?!.\.)
:否定向前看,检查前面是否有2个字符没有点。
注:不知道如何做到这一点在Java中,但我想你应该尝试(?<!\\..)\\.(?!.\\.)
。另外不要忘记加上指向你分裂的句子。
这是一个非常棒的提示,但不能处理像“Dr.Wu is perfect”这样的句子。所以,我做了一些改变,String patternStr2 =“(?<!\\ ..)(?<![A-Z]。)[\\。\\ ?!](?!。\\。)”;然后通过使用java Matcher find()方法,可以得到所有的句子。无论如何,许多非常感谢这个答案! –
@CherryWu不客气:) – HamZa
这听起来像是你需要上下文相关的匹配,这是不能用正则表达式来完成的。 – greedybuddha
除非你只想处理'US'(和** no **的其他缩写),这可以很容易地完成:D – gkalpak
作为聪明地试图理解句子结尾属于哪里的替代方法,你可以尝试用手加入基期结束失败的情况。 – greedybuddha