negated compiled regexp 
Author Message
 negated compiled regexp

I wanted to store some compiled regular expressions in a data
structure then loop through them and append to the structure
based on success of the match.  My problem came when I tried
to construct a "re" that was the opposite of another "re".

Normally, if you want to match anything that doesn't match
a re, you use

$val !~ $re

But I wanted to use a loop that does:
foreach my $re (keys %xxx) {
        if ($val =~ $re) ...

Quote:
}

and have it work for those that should match and others that shouldn't.

So, how to compose a re that is a negated re?  When I started I
actually assumed that there was a negating re operator.  :-)
A perusal of perldoc perlre disabused me of that notion.  The
only thing I could come up with that worked was this:

my (%xxx) = (
  qr{^/       # match first char always just to have something match
      (?!     # negative assertion -- these shouldn't match
        (?:   # Grouping without saving.  Redundant in a lookahead?
            somedir/
            |anotherdir/
            |athirddir/
            |some_other_unwanted_dir/
        )
      )
    }x,                         # No => here -- don't want magic quoting
                       [],      # anon array for pushing into later
  qr{^/somedir/},
                       [],
  qr{^/anotherdir/},
                       [],
);

what I really wanted was something like
  $re = qr{ <NOT> ^/(?:somedir/|anotherdir/
                        |athirddir/|some_other_unwanted_dir/)}x;

#############################################################
1) Am I missing a re operator/modifier that lets me compile a regular
expression that is a negated regular expression?  If one does not
exist, should there be one?

2) My solution won't work if I can't positively match part of the
string.  I have to have something that matches before I can use
the netative lookahead assertion.  True?  My limited testing and
not so limited studying of the documentation seems to support
this, but I'm no regular expression stud.

3) Other than storing a switch in the data structure, can someone
see a better generalized way to do this?

--
// Lee.Lindley   /// Programmer shortage?  What programmer shortage?

////////////////////    50 cent beers are in short supply too.



Sat, 12 Jan 2002 03:00:00 GMT  
 negated compiled regexp
     [courtesy cc of this posting mailed to cited author]

In comp.lang.perl.misc,

:So, how to compose a re that is a negated re?  

I just posted this.  It's in the Cookbook.  Here's the short answer:

    /^(?:(?!PAT).)*$/s

--tom
--
 "Unix isn't fun anymore" --Rob Pike.



Sat, 12 Jan 2002 03:00:00 GMT  
 negated compiled regexp

MCMXCIII in <URL::">
::
:: Looks like I have some boundary condition issues here.  I'll try the
:: recommended way again:
::
::   DB<3> $rex = qr/^(?:(?!PAT).)*$/
::   DB<4> $val = 'PAT'
::   DB<5> print 'true' if ($val =~ $rex)
:: true

That's strange.

$ perl -wle 'print "true" if "PAT" =~ /^(?:(?!PAT).)*$/'
$ perl -wle '$regex = qr /^(?:(?!PAT).)*$/; print "true" if "PAT" =~ $regex'
$ perl -wle '$regex = qr /^(?:(?!PAT).)*$/; print "true" if "PAT" =~ /$regex/'
$ perl -wle '$regex = qr /^(?:(?!PAT).)*$/; $val = "PAT";
              print "true" if $val =~ /$regex/'
$

Perhaps a bug in the de{*filter*}? Nope...

  DB<1> print "true" if "PAT" =~ /^(?:(?!PAT).)*$/

  DB<2>

What version of Perl are you using?

Abigail
--
perl -we 'print split /(?=(.*))/s => "Just another Perl Hacker\n";'

  -----------== Posted via Newsfeeds.Com, Uncensored Usenet News ==----------
    http://www.*-*-*.com/       The Largest Usenet Servers in the World!
------== Over 73,000 Newsgroups - Including  Dedicated  Binaries Servers ==-----



Sat, 12 Jan 2002 03:00:00 GMT  
 negated compiled regexp

:>:So, how to compose a re that is a negated re?  

:>I just posted this.  It's in the Cookbook.  Here's the short answer:

:>    /^(?:(?!PAT).)*$/s

Thanks Tom,

Since Deja keyword seaches don't seem to let you quote pattern
matching chars like '?' and '^', it took some effort to find the post
you mentioned.  Before posting I had looked on Deja with

regular expression (negated|negating)

when I should have just used "regex* negat*".  There may be a language
lesson in that -- root words and common abbreviations.  :-)

I had also skimmed chapter 6 of the Cookbook, and didn't see this,
but since you wrote it I'll take your word for it that it is there.
:-) The Cookbook is at work tonight and I am not.

There are too many things going on with this re that are not
immediately obvious to me.

Whether or not the ^..$ anchors are necessary (I suspect they are).
The grouping of the assertion with a '.' (Have to match something).
The one that really has me spinning is the 0 or more '*' in that thing.
I would have guessed '+'.

Lets try it.  From perl de{*filter*}:
  DB<3> $rex=qr/^(?:(?!PAT).)*$/
  DB<4> $val = ''
  DB<5> print "true" if ($val =~ $rex)
true    # So far so good
  DB<6> $val='PAT'
  DB<7> print "true" if ($val =~ $rex)
true

Ahh Ohh.  What am I missing?  That one through me.
I'll try it my way:

  DB<2> $rex=qr/^(?:(?!PAT).)+$/
  DB<3> $val='PAT'
  DB<4> print 'true' if ($val =~ $rex)
true
  DB<5> $val='/PATH'
  DB<6> print 'true' if ($val =~ $rex)

  DB<7> $val='/PAT'
  DB<8> print 'true' if ($val =~ $rex)
true
  DB<9> $val='PATH'
  DB<10> print 'true' if ($val =~ $rex)

  DB<11>

Looks like I have some boundary condition issues here.  I'll try the
recommended way again:

  DB<3> $rex = qr/^(?:(?!PAT).)*$/
  DB<4> $val = 'PAT'
  DB<5> print 'true' if ($val =~ $rex)
true
  DB<6> $val = '/PAT'
  DB<7> print 'true' if ($val =~ $rex)
true
  DB<8> $val = '/PATH'
  DB<9> print 'true' if ($val =~ $rex)

  DB<10> $val = 'PATH'
  DB<11> print 'true' if ($val =~ $rex)

  DB<12>

It is too late in the evening for me to completely wrap this up.  But
I think your short answer is too short.  This is not enough
information to construct the general case of a negated regular
expression.  Use of the negative lookahead assertion to do this seems
to preclude a match with a re that would match the entire string
(which makes sense).  I'll work on it tommorrow if somebody doesn't
explain it all before then.

But consider that with the introduction of compiled regular
expressions, there may be some need for a more general "negated"
operator for regular expressions..  The traditional use of "!~" vs.
"=~" is no longer adequate unless you can apply the logic to the
compiled version.

--
// Lee.Lindley   /// Programmer shortage?  What programmer shortage?

////////////////////    50 cent beers are in short supply too.
And like 50 cent beers, the quality is sometimes lacking.



Sun, 13 Jan 2002 03:00:00 GMT  
 negated compiled regexp

:>MCMXCIII in <URL::">
:>::
:>:: Looks like I have some boundary condition issues here.  I'll try the
:>:: recommended way again:
:>::
:>::   DB<3> $rex = qr/^(?:(?!PAT).)*$/
:>::   DB<4> $val = 'PAT'
:>::   DB<5> print 'true' if ($val =~ $rex)
:>:: true

:>That's strange.

:>$ perl -wle 'print "true" if "PAT" =~ /^(?:(?!PAT).)*$/'
:>$ perl -wle '$regex = qr /^(?:(?!PAT).)*$/; print "true" if "PAT" =~ $regex'
:>$ perl -wle '$regex = qr /^(?:(?!PAT).)*$/; print "true" if "PAT" =~ /$regex/'
:>$ perl -wle '$regex = qr /^(?:(?!PAT).)*$/; $val = "PAT";
:>              print "true" if $val =~ /$regex/'
:>$

:>Perhaps a bug in the de{*filter*}? Nope...

:>  DB<1> print "true" if "PAT" =~ /^(?:(?!PAT).)*$/

:>  DB<2>

:>What version of Perl are you using?

This is perl, version 5.005_02 built for sun4-solaris

I know it is out of date, but golly, it was the standard release
only a few short months ago.  :-)

I'll upgrade and then try again to unravel all of the ramifications
of negative lookahead assertions.  Bug notwithstanding, I
still don't grok this fully.

Noone has commented on my assertion that there is a need
for a simpler way to build a "!~" compiled regular expression.

--
// Lee.Lindley   /// Programmer shortage?  What programmer shortage?

////////////////////    50 cent beers are in short supply too.



Sun, 13 Jan 2002 03:00:00 GMT  
 negated compiled regexp
:>     [courtesy cc of this posting mailed to cited author]

:>In comp.lang.perl.misc,

:>:So, how to compose a re that is a negated re?  

:>I just posted this.  It's in the Cookbook.  Here's the short answer:

:>    /^(?:(?!PAT).)*$/s

I didn't look hard enough.   Recipe 6.17 discusses this problem
domain at length.

Sorry for wasting everyone's time.

--
// Lee.Lindley   /// Programmer shortage?  What programmer shortage?

////////////////////    50 cent beers are in short supply too.



Sun, 13 Jan 2002 03:00:00 GMT  
 
 [ 6 post ] 

 Relevant Pages 

1. negating a string in a regexp

2. regexp to negate 2 chars at once

3. negating qr// regexp

4. Regexp.compile in perl

5. perlre question - negate POSIX charachter classes

6. Reg Exp - Negating a Word seems IMPOSSIBLE!

7. strange core dump on die conditional on negated pattern match

8. Negating phrases

9. regex negating a search/word

10. Negating (and retaining match) of a regular expression

11. Regular expression, negating sequence

12. Can't Negate Regex /^8([0876])\1\d+$/

 

 
Powered by phpBB® Forum Software