2

40,000 行あり、各行を異なる文に分割する必要があります。今、私はこのようなパターンを使用しています:

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

ほとんどすべての文を処理できますが、次のような文の場合: US Navy, World War I. は 2 つの部分に分けられます: US and Navy, World War I.

この問題を処理する解決策はありますか?

4

3 に答える 3

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.
于 2013-05-16T07:44:38.577 に答える
2

分割したいのに、なぜ一致させようとしているのですか?

次の正規表現を使用します。

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

説明:

  1. (?<!\..):否定後読み、2文字後ろにポイントがないかチェック。

  2. \.: ポイントを合わせます。

  3. (?!.\.):否定先読み、2文字先に点がないかチェック。

オンラインデモ

注: JAVA でこれを行う方法はわかりませんが、試してみるとよいと思います(?<!\\..)\\.(?!.\\.)。また、分割した文章にポイントを追加することを忘れないでください。

于 2013-05-16T08:18:51.253 に答える
0

文字列 patternStr2 = " (?<!\\..)(?<![A-Z].)[\\.\\?!](?!.\\.)"; その後、Java Matcher の find() メソッドを使用すると、すべての文を取得できます。

于 2013-06-24T23:42:22.413 に答える