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

Having a problem with negative look behind assertion

by SirClive (Scribe)
on Feb 12, 2013 at 12:23 UTC ( #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

Comment on Having a problem with negative look behind assertion
Download Code
Replies are listed 'Best First'.
Re: Having a problem with negative look behind assertion
by choroba (Canon) 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 (Abbot) 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 (Abbot) 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
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? | Other CB clients
Other Users?
Others romping around the Monastery: (12)
As of 2015-07-07 22:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (93 votes), past polls