我在Java的正则表达式实现中发现了一些意想不到的行为。使用java.util.regex.Pattern
和java.util.regex.Matcher
时,使用Matcher的find()
方法时,以下正则表达式在输入"Merlot"
上无法正确匹配:
((?:White )?Zinfandel|Merlot)
如果我更改最外侧匹配组中表达式的顺序,则Matcher的find()
方法与匹配。
(Merlot|(?:White )?Zinfandel)
以下是一些说明问题的测试代码。
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在他们的bug数据库中。 (你能听到蟋蟀吗?)
我是否发现了Java中可能经过彻底测试和使用的正则表达式实现的错误(很难相信2013年),或者我做错了什么?
答案 0 :(得分:8)
以下内容:
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
在:
以下内容:
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
答案 1 :(得分:4)
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
答案 2 :(得分:2)
我不明白所有这一切,但我一直在玩你的例子,试图提取一些你可能能够添加到你的错误报告中的诊断信息。
首先,如果你使用占有量词,它可以工作,但我不知道为什么:
Pattern pattern1 = Pattern.compile("((?:White )?+Zinfandel|Merlot)");
此外,如果选择中的第一个组比第二个组短,那么它的工作方式是:
Pattern pattern1 = Pattern.compile("((?:White )?Zinf|Merlot)");
就像我说的,我真的不明白这是怎么回事。这两个发现对我来说都没有任何意义,只是想我会分享......
答案 3 :(得分:2)
该错误显然是 fixed in Java 8 ,并已得到解决,并且未能解决问题' as a backport到Java 7.但是,作为一种解决方法,您可以使用独立(原子)分组来实现" White"或者您可以将“测试案例”与“白色仙粉黛”#34;通过将其包装到单独的交替测试组中。
在您的示例中,第一个捕获组中包含 non-capturing group ,其中包含以下内容。
非捕获组修饰符 (?:白色)
((?:White )?Zinfandel|Merlot)
使用 independent capturing group 的工作将会成功。
独立非捕获组修饰符 (?>白色)
((?>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