Java正则表达式实现中的错误?

我在Java的正则表达式实现中发现了一些意想不到的行为。 使用java.util.regex.Patternjava.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 

我已经validation了在Ubuntu linux上的Java版本1.7.0_11以及OSX 10.8.2上的Java版本1.6.0_37中存在这种意外行为。 我昨天向甲骨文报告了这个行为的错误,并收到了一封自动发送的电子邮件告诉我我的错误报告已经收到并且内部审核ID为2441589.当我在他们的bug中搜索该ID时,我找不到我的错误报告数据库。 (你能听到蟋蟀吗?)

我是否发现了Java中可能经过彻底测试和使用的正则表达式实现的错误(很难相信2013年),或者我做错了什么?

它似乎在Java 1.8中得到修复 。

 Welcome to Scala version 2.11.0-20130930-063927-2bba779702 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0-ea). Type in expressions to have them evaluated. Type :help for more information. scala> import java.util.regex._ import java.util.regex._ scala> Pattern.compile("((?:White )?Zinfandel|Merlot)") res0: java.util.regex.Pattern = ((?:White )?Zinfandel|Merlot) scala> .matcher("Merlot") res1: java.util.regex.Matcher = java.util.regex.Matcher[pattern=((?:White )?Zinfandel|Merlot) region=0,6 lastmatch=] scala> .find() res2: Boolean = true 

下列:

 import java.util.regex.*; public class T { public static void main( String args[] ) { System.out.println( Pattern.compile("(a)?bb|c").matcher("c").find() ); System.out.println( Pattern.compile("(a)?b|c").matcher("c").find() ); } } 

版画

 false true 

上:

  • JDK 1.7.0_13
  • JDK 1.6.0_24

下列:

 import java.util.regex.*; public class T { public static void main( String args[] ) { System.out.println( Pattern.compile("((a)?bb)|c").matcher("c").find() ); System.out.println( Pattern.compile("((a)?b)|c").matcher("c").find() ); } } 

打印:

 true true 

我不明白所有这一切,但我一直在玩你的例子,试图提取一些你可能能够添加到你的bug报告中的诊断信息。

首先,如果你使用占有量词,它可以工作,但我不知道为什么:

Pattern pattern1 = Pattern.compile("((?:White )?+Zinfandel|Merlot)");

此外,如果选择中的第一个组比第二个组短,那么它的工作方式是:

Pattern pattern1 = Pattern.compile("((?:White )?Zinf|Merlot)");

就像我说的,我真的不明白这是怎么回事。 这两个发现对我来说都没有任何意义,但只是想我会分享……

该错误显然已在Java 8中得到修复,并被解决为“不会修复” 作为 Java 7 的后端 。但是,作为一种解决方法,您可以使用“白色”的独立(primefaces)分组,也可以隔离测试将“白仙粉黛”包装成一个单独的交替测试组。

在您的示例中,第一个捕获组内有一个捕获组,其中包含以下内容。

非捕获组修饰符(?:白色)

 ((?:White )?Zinfandel|Merlot) 

随着使用独立捕获组的工作将成功。

独立的非捕获组修饰符(?>白色)

 ((?>White )?Zinfandel|Merlot) 

在Java 1.7.0_71中为独立的非捕获组或组交替重新创建测试用例。

 java version "1.7.0_71" Java(TM) SE Runtime Environment (build 1.7.0_71-b14) Java HotSpot(TM) 64-Bit Server VM (build 24.71-b01, mixed mode) 

独立非捕获组或组替代

 import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexTest { public static void main( String[] args ) { Pattern independentNCG = Pattern.compile( "((?>White )?Zinfandel|Merlot)" ); Matcher independentNCGMatcher = independentNCG.matcher( "Merlot" ); Pattern alternateGroupPattern = Pattern.compile( "(((?:White )?Zinfandel)|Merlot)" ); Matcher alternateGroupMatcher = alternateGroupPattern.matcher( "Merlot" ); System.out.println( independentNCGMatcher.find() ? independentNCGMatcher.group( 0 ) : "No match found for Merlot" ); System.out.println( alternateGroupMatcher.find() ? alternateGroupMatcher.group( 0 ) : "No match found for Merlot" ); } } 

退货

 Merlot Merlot