要查找的多个正则表达式模式。 Java

Multiple regex patterns to find. Java

我需要分别计算字符串中单词和句子的数量,我有这两种工作正常的方法:

    Pattern pattern = Pattern.compile("\w+\s|\w+\,|\w+\.|\w+\?|\w+\!*$");
    Matcher match1 = pattern.matcher(s);
    while(match1.find()) {
        counterWords++;
    }   

和句子:

    Pattern pattern = Pattern.compile("[^?!.][?!.]");
    Matcher match2 = pattern.matcher(s);
    while(match2.find()) {
        counterSentences++;
    }   

下一个任务是再次计算,但是在一个循环中,所以我尝试了:

while(match1.find() || match2.find()){
    if(match1.find()){
        counterWords++;
    }
    if(match2.find()){
        counterSentences++;
    }

然而,该方法无法正常工作,它正确地计算了句子,但单词计数器比实际单词数少了 2 倍。很可能我不完全理解 matcher.find() 是如何工作的,有人可以解释我做错了什么吗? 谢谢。

每次调用 find() 都会搜索下一个匹配项,在组合的 while 循环中,您在每个循环中为 match1 和 match2 调用 find() 两次,首先是在 while 条件中,然后是在 if 条件中,但您只是增加了第二次查找的计数器。

此外,由于您首先在 while 条件中为单词调用 find(),因此永远不会为句子调用 find(),因为单词总是等于或多于句子,并且句子计数器将正常工作。

要用一个循环解决这个问题,你需要你的匹配器找到单词或句末标记,然后告诉你它找到了哪个。这可以使用 "capturing groups".

来完成
    String s = "Hello, user.  How many words and sentences are there?  Count them!";

    int words = 0;
    int sentences = 0;
    Pattern pattern = Pattern.compile("(\w+)|([.?!])");
    Matcher matcher = pattern.matcher(s);

    while(matcher.find()) {
        if (matcher.group(1) != null)
            words++;
        else if (matcher.group(2) != null)
            sentences++;
    }

    System.out.printf("%d words and %d sentences%n", words, sentences);

11 words and 3 sentences

正则表达式解释:

(\w+)|([.?!]) - 在将 \ 翻译成 \
之后 (___)________ - 捕获组 #1。
_\w+_________ - 一个或多个单词字符。
_____|_______ - 匹配表达式的第一部分或第二部分。
______(_____) - 捕获组 #2。
_______[.?!]_ - 句子终止字符。

第一次调用 matcher.find() 将匹配 Hello,将其记录为捕获组 #1。下一次调用跳过逗号和 space 并匹配 user,再次将其记录为捕获组 #1。第三次调用匹配正则表达式第二部分中的句点 (.),将其记录为捕获组 #2。这一直持续到感叹号 (!) 匹配为止。下一次调用 matcher.find() returns false,因为找不到更多匹配项。

if 语句检查组 #1 或组 #2 捕获是否已填写,这确定是否遇到单词或句子终止符。