【发布时间】:2013-07-30 16:00:23
【问题描述】:
去年我在看这个问题:Zero-length matches in Java Regex:
Pattern pattern = Pattern.compile("a?");
Matcher matcher = pattern.matcher("ababa");
while(matcher.find()){
System.out.println(matcher.start()+"["+matcher.group()+"]"+matcher.end());
}
产生输出:
0[a]1
1[]1
2[a]3
3[]3
4[a]5
5[]5
我想知道这是否正确。该模式匹配“a”或空字符串。当 Matcher 指向第一个“b”时,没有“a”,所以 find() 匹配空字符串。
但是,javadoc 说:
此方法在此匹配器区域的开头开始,或者,如果 该方法的先前调用成功并且匹配器具有 没有被重置,在第一个不匹配的字符处 上一场比赛。
所以当 Matcher 指向 'b' 时,没有任何字符被匹配并且 find() 匹配一个空字符串,这意味着之后的第一个字符没有被之前的匹配(即空字符串)匹配到是'b'。这应该意味着下一个 find() 应该从同一个地方开始,根据上面的说法,这意味着代码应该无限循环。但当然这不是正在发生的事情。看起来它只是在匹配一个空字符串时将起点提高 1。
那么怎么了?是实现错误,还是 javadoc 遗漏了什么,或者我遗漏了什么?
【问题讨论】:
-
不,“b”与“a?”不匹配。从输出 1[]1 可以清楚地看出,开始和结束是相同的,所以它是空匹配。但是,在这种情况下 find() 已经消耗了“b”。 ajb 提出的问题是,为什么在这种情况下 find() 会向前发展。答案是匹配组与匹配区域不同(也尝试打印 matcher.regionEnd())。
-
这仍然没有意义。在它匹配第一个“a”之后,它指向“b”。然后第二个 find() 返回空字符串,根据 JLS,匹配器仍应指向“b”以进行下一个 find(),因为第二个 find() 不匹配“b”。所以在我看来,匹配器应该在第二个 find() 之前处于相同的状态,就像在第三个 find() 之前一样......但是它的某些东西是不同的,因为它返回了不同的结果。 regionStart() 和 regionEnd() 也不会改变(我认为它们只是由 region() 改变)。那么有什么不同呢?