Dan Bough
Dan Bough

Reputation: 509

Regex matching string BAR as long as string FOO does not occur before it

I'm trying to write a regex that is only true of a string contains BAR that is not preceded by FOO.

For example, the regex WOULD NOT match this:

FOO IS BAR

But WOULD match this:

BAZ IS BAR

Upvotes: 3

Views: 837

Answers (3)

Tim Pietzcker
Tim Pietzcker

Reputation: 336418

(?<!FOO.*)BAR

is the correct regex for this (but it only works with the .NET regex engine).

(?<!FOO.*) is a negative lookbehind assertion that asserts that it's not possible to match any string containing FOO before the current position.

In PHP, you don't have infinite lookbehind. An alternative would be

^(?:(?!FOO|BAR).)*BAR

Explanation:

^     # Start of string
(?:   # Match...
 (?!  # (unless the following can be matched here:
  FOO #  either FOO
 |    #  or
  BAR #  BAR)
 )    # (end of lookahead)
 .    # ... any character.
)*    # Repeat as needed
BAR   # Match BAR

However, even this doesn't work with the deprecated ereg functions. You need preg functions in order to be able to use lookaround assertions.

But I think there is a way that works with ereg:

^(FO?|[^FO]|[^O]O)*BAR

Explanation:

^      # Start of string
(      # Either match:
 FO?   # F or FO
|      # or
 [^FO] # any character except F or O
|      # or
 [^O]O # any non-O character followed by O
)*     # any number of times
BAR    # Then match BAR

However, this will get very complicated very quickly if your exclusion string is more complicated than FOO...

Upvotes: 4

Andy Lester
Andy Lester

Reputation: 93745

You may find it easier to put it into two regexes. If we're talking Perl, for example, you could do

if ( /BAR/ && !/FOO.*BAR/ )

which to me is much clearer than trying to do the negative lookbehind.

Since you seem to be in PHP, I see nothing wrong with a preg_match on /BAR/ and another on not matching /FOO.*BAR/.

Upvotes: 1

Anirudha
Anirudha

Reputation: 32807

You can use this regex

^(?=.*BAR)(?!.*?FOO.*?BAR).*$
 --------- --------------
     |           |
     |           |proceed only if there's no FOO before BAR...
     |->proceed only if there's a BAR...CHEERS..

Upvotes: 3

Related Questions