How to find a word NOT preceded by another specific word?

perl, php, regex, regex-negation

Solution

Better to use other facilities of the programming language than to look too hard for a regex pattern.

You are looking for strings for which `$s =~ /bar/ and not $s =~ /foo\s*bar/` is true.

The rest of the script below is just for testing.

#!/usr/bin/perl

use strict; use warnings;

my %strings = (
    'foo is bar'  => 1,
    'hello bar'   => 1,
    'foobar'      => 0,
    'foo     bar' => 0,
    'barbar'      => 1,
    'bar foo'     => 1,
    'foo foo'     => 0,
);

my @accept = grep { $strings{$_} } keys %strings;
my @reject = grep { not $strings{$_} } keys %strings;

for my $s ( @accept ) {
    if ( $s =~ /bar/ and not $s =~ /foo\s*bar/ ) {
        print "Good: $s\n";
    }
    else {
        print "Bad : $s\n";
    }
}

for my $s ( @reject ) {
    if ( $s =~ /bar/ and not $s =~ /foo\s*bar/ ) {
        print "Bad : $s\n";
    }
    else {
        print "Good: $s\n";
    }
}

Output:

E:\srv\unur> j
Good: bar foo
Good: hello bar
Good: foo is bar
Good: barbar
Good: foo foo
Good: foo     bar
Good: foobar

Problem

Which regular expression can I use to find all strings `bar` are not preceded by string `foo`? Having whitespace between the two is also illegal. So the regex should match the following strings ``` foo is bar hello bar ``` But not these ``` foobar foo bar ``` I've tried using the following ``` (?!<foo)bar ``` and it gets the work done for eliminating `foobar`, but I need to take care of the whitespace, and of course ``` (?!<foo)\s*bar ``` matches all the strings. Thanks!

Original source