vit has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,
I need to match everything except sequence xyz.
I know that [^xyz] is wrong for this. So how to do this? I did not find it.

Replies are listed 'Best First'.
Re: match with exception
by davis (Vicar) on May 19, 2009 at 12:57 UTC
    I'd be inclined to use the "does not match" feature of !~:
    #!/usr/bin/perl use warnings; use strict; use Data::Dumper; my $string = "asdfxyzasdf"; print "Not found\n" if($string !~ /xyz/);
    Of course, that assumes a regular expression is the best way of (not) matching your string -- if it's just a simple string, then the perl function index() may be more suitable.
    Edit: Changed wording to more accurately reflect test.

    davis

Re: match with exception
by zwon (Abbot) on May 19, 2009 at 13:00 UTC

    maybe you searching something like that:

    $str !~ /xyz/; do_something unless $str =~ /xyz/; do_something unless $str =~ /^xyz$/;
Re: match with exception
by paulchernoch (Acolyte) on May 19, 2009 at 14:18 UTC
    The other answers are correct if all you want to do is not match an entire pattern. But sometimes you want an expression that matches in one part but does not match in another. To do this you need to use look around assertions. For example, if you want a pattern that matches "abc" if it is not followed by "xyz" you would do this:
    my $s = "abcxyQ"; if ($s =~ /abc(?!xyz)/) { print "Matches '$s'\n"; } else { print "Doesn't Match '$s'\n"; } my $t = "abcxyz"; if ($t =~ /abc(?!xyz)/) { print "Matches '$t'\n"; } else { print "Doesn't Match '$t'\n"; }
    The look-ahead assertion is inside the (?!). Read the perl documentation about this feature - it is tricky and does not always work as expected (but it does work as designed!)

    - Paul
Re: match with exception
by AnomalousMonk (Archbishop) on May 19, 2009 at 15:34 UTC
    This depends on just how you define 'everything except sequence xyz'.

    One way (note that a piece of 'xyz', the 'yz', is captured – after all, 'yz' is not 'xyz'!):

    >perl -wMstrict -le "my $s = 'abcxyzdef'; my $exclude = qr{ xyz }xms; my $all_not_xyz = qr{ (?! $exclude) . }xms; my @matches = $s =~ m{ ($all_not_xyz+) }xmsg; print qq{@matches}; " abc yzdef
    Another way (note that the 'xyz' sequence is entirely excluded):
    >perl -wMstrict -le "my $s = 'abcxyzdef'; my $exclude = qr{ xyz }xms; my @matches = split m{ $exclude }xms, $s; print qq{@matches}; " abc def
    These approaches generalize nicely to multiple exclusion sequences:
    >perl -wMstrict -le "my $s = 'abcFOOdefBARghi'; my $exclude = qr{ FOO | BAR }xms; my $all_but = qr{ (?! $exclude) . }xms; my @matches = $s =~ m{ ($all_but+) }xmsg; print qq{@matches}; @matches = split m{ $exclude }xms, $s; print qq{@matches}; " abc OOdef ARghi abc def ghi
Re: match with exception
by JavaFan (Canon) on May 19, 2009 at 15:44 UTC
    I would write (untested, may contain typos):
    /^[^x]*(?:x(?!yz)[^x]*)*$/
    This only does a lookahead after finding an 'x', which ought to be faster than doing a lookahead for each character (which is what /^(?:(?!xyz).)*$/s based solutions do). Of course, the performance difference may not be relevant for you. If needed, the lookahead can entirely be eliminated, but that requires a more complicated regexp - and then I would have to think.