Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Having a problem with negative look behind assertion

by SirClive (Scribe)
on Feb 12, 2013 at 12:23 UTC ( [id://1018345]=perlquestion: print w/replies, xml ) Need Help??

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

In the code below I an trying to test for 'contains bar or Bar but doesn't start with fee' . But I get rows 4 and 5 returned as well as 2 and 3 . What am I doing wrong ?
use strict; use warnings; while(my $line = <DATA>) { chomp($line); if( $line =~ /(?<!fee).*[Bb]ar.*\.java/ ) { print $line . "\n"; } } __DATA__ foo/src/com/stuff/xxxxxx.java foo/src/com/stuff/ggbargg.java foo/src/com/stuff/ggBargg.java fee/src/com/stuff/ggbargg.java fee/src/com/stuff/ggBargg.java
Thanks

Replies are listed 'Best First'.
Re: Having a problem with negative look behind assertion
by choroba (Cardinal) on Feb 12, 2013 at 12:30 UTC
    .* matches fee/src/com/stuff/gg, which is not preceded by fee. See Look Around Assertions for deatils.
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: Having a problem with negative look behind assertion
by Athanasius (Archbishop) on Feb 12, 2013 at 12:41 UTC

    Just use two regexen:

    #! perl use strict; use warnings; while (my $line = <DATA>) { chomp $line; print "$line\n" if $line =~ / [Bb]ar .* \. java $ /x && $line !~ / ^ fee /x; } __DATA__ foo/src/com/stuff/xxxxxx.java foo/src/com/stuff/ggbargg.java foo/src/com/stuff/ggBargg.java fee/src/com/stuff/ggbargg.java fee/src/com/stuff/ggBargg.java

    Output:

    22:32 >perl 531_SoPW.pl foo/src/com/stuff/ggbargg.java foo/src/com/stuff/ggBargg.java 22:37 >

    Hope that helps,

    Update: No need for $line:

    while (<DATA>) { chomp; print "$_\n" if / [Bb]ar .* \. java $ /x && !/ ^ fee /x; }

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: Having a problem with negative look behind assertion
by jethro (Monsignor) on Feb 12, 2013 at 14:08 UTC

    I would say only Athanasius has a correct answer yet, I see mistakes in the other answers. So I made sure and tested. This should work (and still uses only one regex):

    if( $line =~ /^(?!fee).*[Bb]ar.*\.java/ )

    This is a negative look-ahead fixed at the start of the line (with ^).

      I wanted a single regexp if possible and this looks like it does the trick. Many thanks for the replies !

      I would say only Athanasius has a correct answer yet, I see mistakes in the other answers.

      obviously wrong

        If you mean to say your fourth answer is correct I beg to differ. !/fee/ aborts for "fee" anywhere in the string instead of only at the start like the OP wanted

        UPDATE:

        If you mean to say your third answer is correct I beg to differ. It expects a '/' after "fee". While this is always the case in the examples it is not what the OP said (although there is a chance that the OP misstated the problem)

Re: Having a problem with negative look behind assertion
by kcott (Archbishop) on Feb 12, 2013 at 14:10 UTC

    G'day SirClive,

    Another method is to simply skip lines starting with fee then test for [Bb]ar:

    $ perl -Mstrict -Mwarnings -E ' my @data = qw{ foo/src/com/stuff/xxxxxx.java foo/src/com/stuff/ggbargg.java foo/src/com/stuff/ggBargg.java fee/src/com/stuff/ggbargg.java fee/src/com/stuff/ggBargg.java }; for (@data) { next if /^fee/; say if /[Bb]ar/; } ' foo/src/com/stuff/ggbargg.java foo/src/com/stuff/ggBargg.java

    -- Ken

Re: Having a problem with negative look behind assertion
by Anonymous Monk on Feb 12, 2013 at 12:41 UTC

     perl -Mre=debug -E" $_=q{foo/src/com/stuff/ggbargg.java}; m/(?<!fee).*[Bb]ar.*\.java/ "

     perl -Mre=debug -E" $_=q{foo/src/com/stuff/ggbargg.java}; m{(?<!fee)/.*[Bb]ar.*\.java} "

     perl -Mre=debug -E" $_=q{foo/src/com/stuff/ggbargg.java}; m{^(?<!fee)/.*[Bb]ar.*\.java} "

     perl -Mre=debug -E" $_=q{foo/src/com/stuff/ggbargg.java}; !/fee/ and /[Bb]ar.*\.java$/ "

Re: Having a problem with negative look behind assertion
by manorhce (Beadle) on Feb 12, 2013 at 13:40 UTC

    You don't have fixed width of line, look behind or look ahead will only work on fixed width

    use strict; use warnings; while(my $line = <DATA>) { chomp($line); if( $line =~ /(?<!fee\/src\/)(com\/)/ ) { print $line . "\n"; } } __DATA__ foo/src/com/ foo/src/com/ foo/src/com/ fee/src/com/
      Sorry, but that's half wrong. See perldoc perlretut which makes it very clear: look aheads need NOT be fixed width; only the look behind flavor.

      If you didn't program your executable by toggling in binary, it wasn't really programming!

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (6)
As of 2024-03-19 09:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found