为什么这种消极的前瞻不会像我期望的那样发挥作用?

时间:2014-01-23 22:10:50

标签: regex

我正在看这个answer to a stack overflow question。它说使用这个正则表达式来排除某个包含“IT”的名称模式的测试:

^(?!.*IT$).*$

就我而言,我正在尝试排除名为“RestIntegrationTestRunner”的类。我试着写这样的正则表达式:

^.*(?!RestIntegrationTestRunner).*$

但是,这并没有排除那个测试。我不得不这样做:

^(?!.*RestIntegrationTestRunner).*$

为什么它不是第一种方式?我将第一个示例解释为:使用任何以任何东西开头的类,但在名称中包含RestIntegrationTestRunner

我解释第二个正则表达式几乎是一样的:不要使用任何以任何东西开头且包含RestIntegrationTestRunner的类。

那么为什么只有第二个排除“RestIntegrationTestRunner”类?

3 个答案:

答案 0 :(得分:2)

第一个正则表达式将匹配任何字符串。这是因为第一个.*可以匹配整个字符串,剩下的空字符串不等于RestIntegrationTestRunner,因此负前瞻成功,第二个.*匹配空字符串。

然而,第二个正则表达式是diffierently匹配:首先,它匹配任何字符串,因为第二个.*,但然后检查字符串是否匹配.*RestIntegrationTestRunner,即它是否包含RestIntegrationTestRunner,并且失败如果是的话。

答案 1 :(得分:0)

^.*(?!RestIntegrationTestRunner).*$

表示:

  • 从任何事情开始,包括空字符串(贪婪)
  • 紧随其后(负面向前看) .* (也允许为空)

也就是说,第二部分没有多大意义。例如,如果您要排除Foo

四个案例:

xxxFoo
xxxFooyyy
FooFoo
Foo

将全部匹配。

因为整个字符串与第一部分匹配:贪婪匹配任何内容。而你的第二部分,(?!...).*允许为空,所以它不会影响结果。

事实上,这个正则表达式符合您的需求:

^((?!RestIntegrationTestRunner).)*$

答案 2 :(得分:0)

^.*(?!RestIntegrationTestRunner).*$

前面的负面向前放置在初始。*之后,它将匹配整个字符串(直到换行)。如果你打算以。*开头,你会删除第二个。*并使用背后的负面看法:^.*(?<!RestIntegrationTestRunner)$