将句号包括在句子中 - 正则表达式

时间:2013-05-16 06:59:46

标签: java regex pattern-matching divide

我有40,000行,需要将每行分成不同的句子。现在我正在使用这样的模式:

String patternStr2 = "\\s*[\"']?\\s*([A-Z0-9].*?[\\.\\?!]\\s)['\"]?\\s*";

它几乎可以处理所有句子,但对于这样的句子: 美国海军,第一次世界大战 将分为两部分:美国和海军,第一次世界大战。

有没有解决方案可以解决这个问题?

3 个答案:

答案 0 :(得分:2)

好的我认为你应该使用正则表达式,但是我无法抗拒投掷一些。

如果这很难理解,请告诉我,我会添加一些评论......

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 * ._”)

这是相当矫枉过正的,在某些时候可能会出现问题,即如果你的文字在标点符号上不一致的话。


<强>输出继电器

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.

答案 1 :(得分:1)

为什么在拆分时想要匹配

使用以下正则表达式:

(?<!\..)\.(?!.\.)

<强>解释

  1. (?<!\..):负面的背后,检查后面是否有2个字符。

  2. \.:匹配一个点。

  3. (?!.\.):向前看负面,检查前面是否有2个字符。

  4. Online demo

    注意:不确定如何在JAVA中执行此操作,但我认为您应该尝试(?<!\\..)\\.(?!.\\.)。另外,不要忘记为分裂的句子添加一个点。

答案 2 :(得分:0)

String patternStr2 =“(?<!\\..)(?<![A-Z].)[\\.\\?!](?!.\\.)”;然后通过使用java Matcher find()方法,可以获得所有句子。