Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regex: what does (?! ...) mean?

The following regex finds text between substrings FTW and ODP.

/FTW(((?!FTW|ODP).)+)ODP+/

What does the (?!...) do?

like image 584
Nick Heiner Avatar asked Sep 03 '09 02:09

Nick Heiner


2 Answers

(?!regex) is a zero-width negative lookahead. It will test the characters at the current cursor position and forward, testing that they do NOT match the supplied regex, and then return the cursor back to where it started.

The whole regexp:

/
 FTW           # Match Characters 'FTW'
 (             # Start Match Group 1
  (             # Start Match Group 2
   (?!FTW|ODP)   # Ensure next characters are NOT 'FTW' or 'ODP', without matching
   .             # Match one character
  )+            # End Match Group 2, Match One or More times
 )             # End Match Group 1
 OD            # Match characters 'OD'
 P+            # Match 'P' One or More times
/

So - Hunt for FTW, then capture while looking for ODP+ to end our string. Also ensure that the data between FTW and ODP+ doesn't contain FTW or ODP

like image 118
gnarf Avatar answered Sep 28 '22 07:09

gnarf


From perldoc:

A zero-width negative look-ahead assertion. For example /foo(?!bar)/ matches any occurrence of "foo" that isn't followed by "bar". Note however that look-ahead and look-behind are NOT the same thing. You cannot use this for look-behind.

If you are looking for a "bar" that isn't preceded by a "foo", /(?!foo)bar/ will not do what you want. That's because the (?!foo) is just saying that the next thing cannot be "foo"--and it's not, it's a "bar", so "foobar" will match. You would have to do something like /(?!foo)...bar/ for that. We say "like" because there's the case of your "bar" not having three characters before it. You could cover that this way: /(?:(?!foo)...|^.{0,2})bar/ . Sometimes it's still easier just to say:

if (/bar/ && $` !~ /foo$/)
like image 28
mkoryak Avatar answered Sep 28 '22 05:09

mkoryak