in reply to search for 'cat' not followed by 'dog'

You want a "negative lookahead":

use warnings; use strict; while(<DATA>){ print if / cat # word cat (?: # do not capture (?! # negative lookahead \s* # possible whitespace dog # the word dog ) # end negative lookahead ) # end do not capture group /x; # /cat(?:(?!\s*dog))/ } __DATA__ my cat loves dogs catdog cat dog dog dog dog cat dog dog cat not a dog

Output:

my cat loves dogs dog cat not a dog

Note that the above will also match things like cat doggle, so if you *only* want it to match the word "dog", you'll have to put a boundary at the end of that word in the regex.

Update: AnomalousMonk pointed out below that the non-capture portion is not required here. For posterity, I'll leave it in (unless someone advises it'd be best to remove). So essentially, the second and last lines in the regex above are not needed.

Replies are listed 'Best First'.
Re^2: search for 'cat' not followed by 'dog'
by AnomalousMonk (Archbishop) on Jan 28, 2019 at 20:15 UTC
    # /cat(?:(?!\s*dog))/

    I don't understand why you wrap  (?!\s*dog) in a non-capturing group.


    Give a man a fish:  <%-{-{-{-<

      Old habit that I write in a non-capture when I'm doing grouping. In this case, after some *quick* testing, I realize that the negative lookahead doesn't appear to capture by default. In fact, even with benchmarking, the non-cap is effectively no more efficient than leaving it out.

        Note that even if the lookarounds did capture, putting a non-capturing group around a capturing group doesn't stop it from capturing, i.e. "x"=~/(?:(x))/ still puts "x" in $1 (you can even do funky stuff like "xyz"=~/(?=(y))/ which will capture "y" without advancing the match position past it).

        As of 5.22 you can say (?n:...) and any capture groups inside will be non-capturing.