Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

negative regex without !~

by mbr (Sexton)
on Jul 22, 2004 at 15:27 UTC ( [id://376620]=perlquestion: print w/replies, xml ) Need Help??

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

Hi.

I'm trying to come up with a single regex that will match a string as long as it does not contain a particular pattern. This would be easy, except that I would like to do it without using the !~ operator. Variants of m|^.*($!badstuff)| do not work for reasons explained in "man perlre". Any other way to do this? Note: I'm working with a piece of software that makes use of regular expressions, but apparently it cannot do negative matches with something like !~, so this sparked my curiosity about how to negative match without !~. Thanks.

Replies are listed 'Best First'.
Re: negative regex without !~
by hv (Prior) on Jul 22, 2004 at 16:18 UTC

    This should do it:

    /^(?!.*$pattern)/;

    If the string can include newlines there are a couple of ways to replace the '.' without changing the meaning of $pattern:

    /^(?!.*(?-s:$pattern))/s; /^(?![\d\D]*$pattern)/;

    Hugo

      That is exactly what I was looking for. Thanks.
Re: negative regex without !~
by dragonchild (Archbishop) on Jul 22, 2004 at 15:34 UTC
    if ($string !~ /asdfasdf/) { ... } is equivalent to if (! ($string =~ /asdfasdf/) ) { ... } or unless ($string =~ /asdfasdf/) { ... }

    If that doesn't suffice, a better problem description is required.

    Update: Fixed precendence issue that merlyn correctly noted.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

    I shouldn't have to say this, but any code, unless otherwise stated, is untested

      if ($string !~ /asdfasdf/) { ... } is equivalent to if (! $string =~ /asdfasdf/) { ... }
      Not really. The latter parses as if ((! $string) =~ /asdfasdf/) {....} That's why not was invented... because the precedence of "!" is often far too high for most operations.

      -- Randal L. Schwartz, Perl hacker
      Be sure to read my standard disclaimer if this is a reply.

Re: negative regex without !~
by davido (Cardinal) on Jul 22, 2004 at 15:42 UTC

    In Perl, the following examples are functionally equivilant, though they get to that equivilancy in different ways.

    if ( $string !~ m/pattern/ ) { ..... }

    And.....

    if ( not $string =~ m/pattern/ ) { ...... }

    And.....

    unless ( $string =~ m/pattern/ ) { ...... }

    Does your special language provide you with More Than One Way To Do It? ;)


    Dave

Re: negative regex without !~
by diotalevi (Canon) on Jul 22, 2004 at 17:08 UTC
    /(?:$RegexGoesHere(?!)|(?=))/

    Ok, right. The previous construction was incorrect. I think using the experimental conditional test would work here since now the (?!) does not connect via backtracking to the (?=).

    /(?((?:$RegexGoesHere))(?!)|(?=))/
      Doesn't work. (?!) just makes it take the second alternative. People have proposed a FAIL HERE mechanism, but there isn't one now.

      The alternate way (much worse than hv's IMO) that you sometimes see is (IIRC) /^(.(?!$regex))*\z/s

      Update: oops

      Ooh yes, that's much cleaner than my attempt. (You don't need the '(?=)' in there, but it's probably clearer with than without.)

      Hugo

Re: negative regex without !~
by Plankton (Vicar) on Jul 22, 2004 at 16:35 UTC
Re: negative regex without !~
by Anonymous Monk on Jul 22, 2004 at 18:25 UTC
    To match strings not containing foo how about qr/^(?:[^f]|f[^o]|fo[^o])*(?:f|fo)?$/ ?

    Edited by Chady -- code tags.

Re: negative regex without !~
by arden (Curate) on Jul 22, 2004 at 15:36 UTC
    What piece of software are you dealing with that "cannot do negative matches"? I'm going to go out on a limb here and guess it isn't Perl, which leads to my second question: What does this have to do with Perl? Why are you asking at PerlMonks?

    Again, if your "special" software doesn't allow for !~ then how are we to guess at if something else will succeed or fail within this "special" software without knowing what that software is?

    - - arden.

      I'm going to go out on a limb here and guess it isn't Perl

      A questionable assumption. Define Perl.

      One likely scenario is software compiled with the PCRE library. A growing number of applications do so these days. I know Apache will use it if it's there (although I don't know what for... maybe mod_rewrite these days?) and so will Postfix (and I'm a heavy user of it and very happy it's available).

      A pure-Perl scenario I can envisage is a callback/library situation, where you get to construct an object or otherwise pass a qr/.../ where the design (admittedly somewhat brain-damaged) only admits positive matches. The not, ! and unless solutions in the other responses does one no good if you can't manoeuvre around the code that's doing the matching.

      So please don't be so hasty in dismissing a person and telling them to go away. I agree the OP should have provided more information, but since it was posted here, maybe it has something to do with Perl?

      - another intruder with the mooring of the heat of the Perl

      There are many perl CGI and Tk programs that ask a user to enter regular expressions. If you are entering a regular expression in an entry box you typically cannot put '!~' on the front of it to negate it. I don't know if this is the kind of thing the original poster is talking about, but it seems like a very possible scenario
        File::Repl has a function that takes a qr (or a string that will be eval'ed as a regex), for instance. If I want to make a zip of a directory containing all files that are not ending in ".obj" and also do not contain the string "super-secret-gamma-ray-gun", I can't do that with File::Repl and I have to post-match.
      I'm fairly sure the $foo !~ m/../ syntax didn't exist in perl 5.0, but my impression to the original poster's question is that it really doesn't relate to perl itself of any version. I used to have to write a lot of backwards compatible code, so this was useful knowledge.... but who's still using 5.0 these days <grin>
        Works in 5.005

        but who's still using 5.0 these days?

        <sheepishly> Me. Some companies haven't upgraded.... </sheepishly>

        use strict; print 'Perl version is: ', $]; my @foo = qw/ fee fie fo fum big bag boz /; foreach ( @foo ) { if ( $_ !~ /f/ ) { print "Matched: $_ !~ /f/ " ; } else { print "Failed: $_ !~ /f/ " ; } } Output: Perl version is: 5.00503 Failed: fee !~ /f/ Failed: fie !~ /f/ Failed: fo !~ /f/ Failed: fum !~ /f/ Matched: big !~ /f/ Matched: bag !~ /f/ Matched: boz !~ /f/

        -------------------------------------
        Nothing is too wonderful to be true
        -- Michael Faraday

        No, I recall using !~ even back in Perl 4.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://376620]
Approved by grinder
Front-paged by grinder
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (3)
As of 2024-03-29 02:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found