Reputation: 509
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
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
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
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