8

为了重现最近一个问题中所述的问题 -为什么 (.*)* 进行两次匹配并且在组 $1 中不选择任何内容?我尝试了括号内外的 and 的各种组合,结果出乎我的*意料。+

我本来期望输出与该问题中已接受的答案中解释的输出相同,并且在另一个重复的问题中,标记为Perl-为什么 .* 不消耗此 Perl 正则表达式中的整个字符串?. 但它的行为方式并不相同。

为简单起见,这是我尝试过的代码:-

String str = "input";
String[] patterns = { "(.*)*", "(.*)+", "(.+)*", "(.+)+" };

for (String pattern: patterns) {
    Matcher matcher = Pattern.compile(pattern).matcher(str);

    while (matcher.find()) {
        System.out.print("'" + matcher.group(1) + "' : '" + matcher.start() + "'" + "\t");
    }

    System.out.println();
}

这是我得到的所有 4 个组合的输出:-

'' : '0'    '' : '5'            // For `(.*)*`
'' : '0'    '' : '5'            // For `(.*)+`  
'input' : '0'   'null' : '5'    // For `(.+)*`
'input' : '0'                   // For `(.+)+`

现在,我无法理解,为什么输入1st和输出,2nd我没有得到整个字符串first resultmatcher.find()我的意思是,理想情况下,在第一种情况下,.*应该首先捕获整个字符串,然后empty string在最后捕获。现在,虽然它在第二场比赛中给出了预期的结果,但它的表现并不好1st match

而且,在第二种情况下,我什至不应该得到第二场比赛,因为我+在括号外有一个量词。

我的预期输出是: -

'input' : '0'   '' : '5'  // For 1st
'input' : '0'    // For 2nd

另外,在3rd输出中,为什么我得到了null第二场比赛而不是empty string?前三个组合的第二场比赛不应该相同吗?

第四个输出符合预期。所以,毫无疑问。

4

1 回答 1

7

您正在看到您在链接到的问题中看到的相同现象的影响:

对于(.*)*

  • 第一个matcher.start()0因为那是匹配 ( "input") 开始的地方。
  • 第一个matcher.group(1)""因为 repeat已经用空字符串(.*)覆盖了捕获的内容(但确实包含)。"input"matcher.group(0)input"
  • 第二个matcher.start()5因为这是第一次成功匹配后正则表达式引擎所在的位置。
  • 第二个matcher.group(1)(以及matcher.group(0))是""因为这就是字符串末尾要匹配的全部内容。

因为(.*)+它是一样的。毕竟,空字符串可以重复多次,并且仍然是空字符串。

因为(.+)*null第二个匹配成功时(长度为 1 的字符串的零次重复匹配空字符串),捕获括号无法捕获任何内容,所以它的内容是null(如未定义,而不是空字符串)。

于 2013-01-24T12:04:24.427 回答