【发布时间】:2013-02-05 17:05:44
【问题描述】:
我在 Java 的正则表达式实现中发现了一些意外行为。在使用java.util.regex.Pattern 和java.util.regex.Matcher 时,使用Matcher 的find() 方法时,以下正则表达式无法正确匹配输入"Merlot":
((?:White )?Zinfandel|Merlot)
如果我改变最外层匹配组内表达式的顺序,Matcher 的find() 方法确实匹配。
(Merlot|(?:White )?Zinfandel)
这里有一些说明问题的测试代码。
RegexTest.java
import java.util.regex.*;
public class RegexTest {
public static void main(String[] args) {
Pattern pattern1 = Pattern.compile("((?:White )?Zinfandel|Merlot)");
Matcher matcher1 = pattern1.matcher("Merlot");
// prints "No Match :("
if (matcher1.find()) {
System.out.println(matcher1.group(0));
} else {
System.out.println("No match :(");
}
Pattern pattern2 = Pattern.compile("(Merlot|(?:White )?Zinfandel)");
Matcher matcher2 = pattern2.matcher("Merlot");
// prints "Merlot"
if (matcher2.find()) {
System.out.println(matcher2.group(0));
} else {
System.out.println("No match :(");
}
}
}
预期的输出是:
Merlot
Merlot
但实际输出是:
No Match :(
Merlot
我已经验证了这种意外行为存在于 Ubuntu linux 上的 Java 版本 1.7.0_11 和 OSX 10.8.2 上的 Java 版本 1.6.0_37 中。我昨天将此行为作为错误报告给Oracle,并收到一封自动电子邮件,告诉我我的错误报告已收到,内部审核 ID 为 2441589。当我在中搜索该 ID 时找不到我的错误报告他们的错误数据库。 (你能听到蟋蟀的声音吗?)
我是否发现了 Java 可能经过彻底测试和使用的正则表达式实现中的一个错误(在 2013 年很难相信),还是我做错了什么?
【问题讨论】:
-
如果你这样做
(((?:White )?Zinfandel)|Merlot)或((?:(?:White )?Zinfandel)|Merlot)会发生什么? -
这可能是范围问题吗?连接是否优先于(如我所料) | (选择)?
-
看起来 matches() 有效,但 find() 无效。
-
这是我能找到的最简单的正则表达式,但未能找到:
Pattern.compile("()?.|").matcher("").find() -
不管怎样,这种行为也存在于 Windows 7 上的 Java 版本 1.7.0_21 上。