正規表現の一致数をカウントするにはどうすればよいですか?


97

これを含む文字列があるとしましょう:

HelloxxxHelloxxxHello

パターンをコンパイルして「Hello」を探します

Pattern pattern = Pattern.compile("Hello");
Matcher matcher = pattern.matcher("HelloxxxHelloxxxHello");

3つの一致が見つかるはずです。一致の数をカウントするにはどうすればよいですか?

さまざまなループを試してみましたmatcher.groupCount()が、うまくいきませんでした。


検索文字列が入力文字列で重複して出現する可能性はありますか?
aioobe 2011

回答:


177

matcher.find()すべての一致は検索されず、次の一致のみが検索されます。

Java 9以降のソリューション

long matches = matcher.results().count();

Java 8以前のソリューション

次のことを行う必要があります。(Java 9以降、より優れたソリューションがあります

int count = 0;
while (matcher.find())
    count++;

ところで、matcher.groupCount()まったく違うものです。

完全な例

import java.util.regex.*;

class Test {
    public static void main(String[] args) {
        String hello = "HelloxxxHelloxxxHello";
        Pattern pattern = Pattern.compile("Hello");
        Matcher matcher = pattern.matcher(hello);

        int count = 0;
        while (matcher.find())
            count++;

        System.out.println(count);    // prints 3
    }
}

重複する一致の処理

上記のスニペットaaaaaaの一致をカウントすると、2が得られます。

aaaa
aa
  aa

3つの一致、つまりこの動作を取得するには:

aaaa
aa
 aa
  aa

<start of last match> + 1次のようにインデックスで一致を検索する必要があります。

String hello = "aaaa";
Pattern pattern = Pattern.compile("aa");
Matcher matcher = pattern.matcher(hello);

int count = 0;
int i = 0;
while (matcher.find(i)) {
    count++;
    i = matcher.start() + 1;
}

System.out.println(count);    // prints 3

文字列内で発生する一致の数を数えます。java.util.regex.Matcher.region(int start、int end)メソッドは、この正規表現エンジンの領域の制限を設定します。リージョンは、一致を見つけるために検索される入力シーケンスの一部です。このメソッドを呼び出すと、マッチャーがリセットされ、開始パラメーターで指定されたインデックスで開始し、終了パラメーターで指定されたインデックスで終了するように領域が設定されます。これを試して。while(matcher.find()){ matcher.region(matcher.end()-1, str.length()); count++; }
Mukesh Kumar Gupta

17

これは、重複する可能性がある一致に対して機能するはずです。

public static void main(String[] args) {
    String input = "aaaaaaaa";
    String regex = "aa";
    Pattern pattern = Pattern.compile(regex);
    Matcher matcher = pattern.matcher(input);
    int from = 0;
    int count = 0;
    while(matcher.find(from)) {
        count++;
        from = matcher.start() + 1;
    }
    System.out.println(count);
}


3

Java 8ストリームを使用するwhile必要があり、ループにアレルギーがある場合は、これを試すことができます。

public static int countPattern(String references, Pattern referencePattern) {
    Matcher matcher = referencePattern.matcher(references);
    return Stream.iterate(0, i -> i + 1)
            .filter(i -> !matcher.find())
            .findFirst()
            .get();
}

免責事項:これはばらばらのマッチでのみ機能します。

例:

public static void main(String[] args) throws ParseException {
    Pattern referencePattern = Pattern.compile("PASSENGER:\\d+");
    System.out.println(countPattern("[ \"PASSENGER:1\", \"PASSENGER:2\", \"AIR:1\", \"AIR:2\", \"FOP:2\" ]", referencePattern));
    System.out.println(countPattern("[ \"AIR:1\", \"AIR:2\", \"FOP:2\" ]", referencePattern));
    System.out.println(countPattern("[ \"AIR:1\", \"AIR:2\", \"FOP:2\", \"PASSENGER:1\" ]", referencePattern));
    System.out.println(countPattern("[  ]", referencePattern));
}

これは出力します:

2
0
1
0

これは、ストリームとの素な一致の解決策です。

public static int countPattern(String references, Pattern referencePattern) {
    return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
            new Iterator<Integer>() {
                Matcher matcher = referencePattern.matcher(references);
                int from = 0;

                @Override
                public boolean hasNext() {
                    return matcher.find(from);
                }

                @Override
                public Integer next() {
                    from = matcher.start() + 1;
                    return 1;
                }
            },
            Spliterator.IMMUTABLE), false).reduce(0, (a, c) -> a + c);
}

1

以下のコードを使用して、正規表現が入力で見つけた一致の数を見つけます

        Pattern p = Pattern.compile(regex, Pattern.MULTILINE | Pattern.DOTALL);// "regex" here indicates your predefined regex.
        Matcher m = p.matcher(pattern); // "pattern" indicates your string to match the pattern against with
        boolean b = m.matches();
        if(b)
        count++;
        while (m.find())
        count++;

これは特定のコードではなく一般化されたコードです。ニーズに合わせて調整してください

間違いがありましたら遠慮なく訂正してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.