单引号查找的Java正则表达式错误?

单引号查找的Java正则表达式错误?,java,regex,string,Java,Regex,String,可能是一个我还没有看到的PEBKAC,但是:(?:[^']+|“”)+应该匹配带有非双引号的字符串(基于并测试) 但是,如果您在Java模式对象中使用上述内容,即,Pattern noSingleQuote=Pattern.compile((?:[^']+|''')+”则行为如下所示: 如果匹配的字符串不包含单引号,则一切正常,匹配器返回true(即,noSingleQuote.Matcher(“tester”).matches()和noSingleQuote.Matcher(“tes”).m

可能是一个我还没有看到的PEBKAC,但是:
(?:[^']+|“”)+
应该匹配带有非双引号的字符串(基于并测试)

但是,如果您在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,我没有看到:)