单引号查找的Java正则表达式错误?
可能是一个我还没有看到的PEBKAC,但是:单引号查找的Java正则表达式错误?,java,regex,string,Java,Regex,String,可能是一个我还没有看到的PEBKAC,但是:(?:[^']+|“”)+应该匹配带有非双引号的字符串(基于并测试) 但是,如果您在Java模式对象中使用上述内容,即,Pattern noSingleQuote=Pattern.compile((?:[^']+|''')+”则行为如下所示: 如果匹配的字符串不包含单引号,则一切正常,匹配器返回true(即,noSingleQuote.Matcher(“tester”).matches()和noSingleQuote.Matcher(“tes”).m
(?:[^']+|“”)+
应该匹配带有非双引号的字符串(基于并测试)
但是,如果您在Java模式对象中使用上述内容,即,Pattern noSingleQuote=Pattern.compile((?:[^']+|''')+”代码>则行为如下所示:
- 如果匹配的字符串不包含单引号,则一切正常,匹配器返回true(即,
noSingleQuote.Matcher(“tester”).matches()
和noSingleQuote.Matcher(“tes”).matches()
正常)
- 如果匹配的字符串包含单引号,则JDK
Matcher
在内部命中无限循环(即,noSingleQuote.Matcher(“tes'ter”).matches()
导致无限循环)
在8u112上进行本地测试,并使用
我还没有深入调试无限循环发生的确切原因和位置
有什么想法和见解吗
更新:给定的示例不再现所描述的行为,使用“选择x,y,z,其中x='t'”;
和“选择x,y,z,其中x='t'”;“
再现了上述内容。
对我来说,这意味着bug(?)不仅仅是因为单引号
Update2:它不是一个无限循环,但它似乎与字符串本身的空格数成正比。因为我遇到的生产代码有一个很长的字符串,有很多空格,所以我假设它是一个无限循环。我错了。我想你的无限循环在别处
Pattern p = Pattern.compile("(?:[^']+|'')+");
public void test(String test) {
System.out.println("\ntest = [" + test + "]");
Matcher m = p.matcher(test);
while (m.find()) {
System.out.println("Found!");
for (int i = 0; i <= m.groupCount(); i++) {
System.out.println("Matched (" + i + ") '" + m.group(i) + "'");
}
}
}
private void test() {
test("select x, y, z where x = ''t'';");
test("select x, y, z where x = 't'';");
test("tes'ter");
}
Pattern p=Pattern.compile((?:[^']+|“”)+”;
公共无效测试(字符串测试){
System.out.println(“\ntest=[“+test+”]);
匹配器m=p.匹配器(测试);
while(m.find()){
System.out.println(“Found!”);
对于(int i=0;i我想您遇到了我在中描述的一个已知问题。简而言之,原因是Java正则表达式引擎以一种低效的方式处理量化的替换,使用这种模式是一个好主意
在您的情况下,模式应定义为
String pattern = "[^']*(?:''[^']*)*";
在这里,逻辑是线性的,很少有回溯:
[^']*
-除'
(?:''[^']*)*
-零个或多个以下序列:
'
-双单引号
[^']*
-除'
以外的零个或多个字符
您是否尝试过转义'
字符?@I.G.Pascual why?。可能Java将'
视为一个特殊字符,需要进行转义escaped@I.G.Pascual我不知道转义单引号会有什么不同,但是我测试了它:用\\或\\转义所有单引号不会有什么不同(在输入字符串中、模式中或两者中)。只需在本地jdk1.8.0_66中尝试相同的代码,即可完美运行…看起来您的jdk一团糟…请参阅@WiktorStribiżew-答案的要点是它应该有助于OP解决问题。-我怀疑OP没有在组或m.find()上迭代
正确调用。这将证明这样做是正确的。@OldCurmudgeon OP甚至没有提到matcher#find()
,它是关于matcher#matches()
感谢您提供了详细的源代码支持的答案。正如我在问题的第一句中所写的:这是一个PEBKAC,我没有看到:)