Daniel Kaplan
Daniel Kaplan

Reputation: 67310

Why doesn't this negative lookahead work the way I expect?

I was looking at this answer to a stack overflow question. It said to use this regex to exclude a certain test with a name pattern that contains "IT":

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

In my case, I'm trying to exclude a class with the name of "RestIntegrationTestRunner". I tried writing a regex like this:

^.*(?!RestIntegrationTestRunner).*$

But, this didn't exclude that test. I had to do this:

^(?!.*RestIntegrationTestRunner).*$

Why doesn't it work the first way? I interpret the first example to mean this: Use any classes that start with anything, but don't contain RestIntegrationTestRunner in the name.

I interpret the second regex to be saying pretty much the same thing: Don't use any classes that start with anything and contain RestIntegrationTestRunner.

So why does only the second one exclude the "RestIntegrationTestRunner" class?

Upvotes: 1

Views: 305

Answers (3)

adamdc78
adamdc78

Reputation: 1161

^.*(?!RestIntegrationTestRunner).*$

The negative look ahead is placed after the initial .* which will match your entire string (up until a newline). If you're going to begin with a .* you would remove the second .* and use a negative look behind: ^.*(?<!RestIntegrationTestRunner)$

Upvotes: 0

Kent
Kent

Reputation: 195029

^.*(?!RestIntegrationTestRunner).*$

means:

  • start with anything, including empty string (greedy)
  • followed(negative look ahead).* (allows empty too)

that is, the 2nd part doesn't make much sense. For example, if you want to exclude Foo:

four cases:

xxxFoo
xxxFooyyy
FooFoo
Foo

will be all matched.

Because the whole string matches the first part: greedy match anything. And your 2nd part, the (?!...).* allows empty, so it doesn't affect the result.

In fact, this regex would match your needs:

^((?!RestIntegrationTestRunner).)*$

Upvotes: 0

Njol
Njol

Reputation: 3279

The first regex will match any string. This is because the first .* can match the whole string, and the remaining empty string isn't equal to RestIntegrationTestRunner, thus the negative look-ahead succeeds, and the second .* matches the empty string.

The second regex however matches diffierently: First, it matches any string due to the second .*, but then the string is checked for whether it matches .*RestIntegrationTestRunner, i.e. whether it contains RestIntegrationTestRunner, and fails if it does.

Upvotes: 2

Related Questions