java正则表达式匹配计数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java正则表达式匹配计数相关的知识,希望对你有一定的参考价值。

假设我有一个文件,该文件包含:

HelloxxxHelloxxxHello

我编译一个模式来寻找'你好'

Pattern pattern = Pattern.compile("Hello");

然后我使用输入流来读取文件并将其转换为String,以便可以进行正则表达式。

一旦匹配器在文件中找到匹配项,它就表明了这一点,但它没有告诉我它找到了多少匹配项;只是它在String中找到了一个匹配项。

因此,由于字符串相对较短,并且我使用的缓冲区是200字节,因此它应该找到三个匹配项。但是,它只是简单地说匹配,并没有向我提供有多少匹配的计数。

计算String中发生的匹配数的最简单方法是什么。我已经尝试了各种for循环并使用matcher.groupCount(),但我无处可去。

答案

matcher.find()没有找到所有的比赛,只有下一场比赛。

你必须做以下事情:

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
    }
}

处理重叠匹配

aa中计算aaaa的匹配时,上面的代码片段会给你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
另一答案

这适用于非不相交的匹配:

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);
}
另一答案

这可能有所帮助:

public static void main(String[] args) {
    String hello = "HelloxxxHelloxxxHello";
    String []matches = hello.split("Hello");
    System.out.println(matches.length);    // prints 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);
}

以上是关于java正则表达式匹配计数的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式匹配特定的 URL 片段而不是所有其他 URL 可能性

循环通过 python 正则表达式匹配

JAVA正则表达式代码

通过 Java 正则表达式提取 semver 版本字符串的片段

oracle10g中,如何查询正则表达式匹配指定字符串的匹配个数?

用JAVA语言编写正则表达式匹配指定的汉字的方法