为什么这个字符串匹配,即使它的部分是负向前瞻

时间:2018-03-28 13:55:20

标签: java regex regular-language

为什么这个正则表达式

(?!(public|private|protected|abstract|final|static))(.*)\(\);

匹配此字符串:

public Test();

即使我说我想要一个空的空格,然后没有 (public|...)然后是一些东西然后是();?我在这里做错了什么?

但我希望与此匹配:Test();

编辑:

为什么这不起作用(找不到匹配项),即使regex101.com与Test();匹配?

final String test = "public class Test {\n" +
        "  Test();\n";

final Pattern ptrn = Pattern.compile("^  (?!(public|private|protected|abstract|final|static))(.*)\\(\\);");
final Matcher mtchr = ptrn.matcher(test);

while(mtchr.find())
    System.out.println("FOUND");

1 个答案:

答案 0 :(得分:3)

问题

您遇到的问题显示在下面的代码段中。正则表达式是匹配的,因为你的正则表达式没有锚定到字符串中的某个位置。这意味着正则表达式将尝试匹配字符串中的每个位置。

正则表达式将首先尝试匹配p中的public Test();。由于否定前瞻包含public,因此会失败并尝试下一个位置:u中的ublic Test();。由于public和其他条款在此位置不存在,因此匹配成功!

var s = 'public Test();'
var r = /(?!(public|private|protected|abstract|final|static))(.*)\(\);/

console.log(s.match(r)[0])

修复

那么我们该如何解决这个问题呢?简单:锚定图案。添加^锚点会强制正则表达式从字符串的开头匹配。这意味着它只会尝试从字符串的开头(ppublic Test();的位置)进行匹配,并且不会尝试匹配字符串开头的任何位置(它不会尝试匹配u)。

See regex in use here

^(?!(public|private|protected|abstract|final|static))(.*)\(\);

var a = [
  'public Test();',
  'Test();'
]
var r = /^(?!(public|private|protected|abstract|final|static))(.*)\(\);/

a.forEach(function(s) {
  console.log(r.test(s) ? s.match(r)[0] : '*** no match')
})