Java正则表达式中``(。*)*`,`(。*)+`,`(。+)*`的奇怪问题

时间:2013-01-24 11:58:21

标签: java regex

为了重新解决最近问题中提到的问题 - Why does (.*)* make two matches and select nothing in group $1?我在括号内外尝试了*+的各种组合,结果我没想到得到了。

我原本期望输出,与该问题中接受的答案中解释的输出相同,以及另一个重复的问题,标记在Perl - Why doesn't the .* consume the entire string in this Perl regex?下。但它的行为方式并不一样。

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

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 `(.+)+`

现在,我无法理解,为什么在1st2nd输出中,我没有将first result的整个字符串作为matcher.find()。我的意思是,理想情况下,在第一种情况下,.*应首先捕获整个字符串,然后在最后捕获empty string。现在,虽然它给出了第二场比赛的预期结果,但它对1st match表现不佳。

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

我的预期输出是: -

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

此外,在3rd输出中,为什么我将null作为第二场比赛而不是empty string?第3组合的第2场比赛不应该相同吗?

第4次输出符合预期。所以,毫无疑问。

1 个答案:

答案 0 :(得分:7)

您正在看到您在与之关联的问题中看到的相同现象的影响:

(.*)*

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

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

对于(.+)*,您得到null,因为第二个匹配成功(长度为1的字符串的零重复与空字符串匹配),捕获括号无法捕获任何内容,因此其内容为null(如未定义,而不是空字符串)。