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

Hello guys : I have this pice :
while (<OUT>) { push(@hold1, $1) && last if (m/(\w+\.bld)/); } my $hold11 = join(' ', @hold1);
where I am trying to only mach the .bld that aren't follwed with # like in the follwing data :
../nbssbase/ip/bld/libipGH040.bld:57:# Reflecting change of eni.cxx ../nbssbase/ip/bld/libipGH060.bld:60:# Reflecting change of eni.cxx ../nbssbase/ip/bld/lib.bld:17:eni.cxx
I only want to match the .bld in the third line since it is not followed # , so my code is catching the first one , I do wanna catch only one but not the ones followed by # .. so do you see the problem .. thanks

Replies are listed 'Best First'.
Re: match and regex
by Shendal (Hermit) on Aug 13, 2002 at 19:34 UTC
    Use a zero-width negative lookahead assertion:
    #!/usr/bin/perl -w use strict; foreach (<DATA>) { print "$1\n" if (m|(\w+\.bld)(?!\S*#)|) } __DATA__ ../nbssbase/ip/bld/l?ibipGH040.bld:57:# Reflecting change of eni.cxx ../nbssbase/ip/bld/l?ibipGH060.bld:60:# Reflecting change of eni.cxx ../nbssbase/ip/bld/l?ib.bld:17:eni.cxx


    Cheers,
    Shendal
      thanks ,, it works , would you mind explaining this part to me :
      (?!\S*#)
        I could, but I think that perldoc perlre can give a better explanation:
        (?!pattern) A zero-width negative lookahead assertion. For example /foo(?!bar)/ matches any occurrence of "foo" that isn't followed by "bar". Note however that lookahead and lookbehind are NOT the same thing. You cannot use this for lookbehind. If you are looking for a "bar" that isn't preceded by a "foo", /(?!foo)bar/ will not do what you want. That's because the (?!foo) is just saying that the next thing cannot be "foo"--and it's not, it's a "bar", so "foobar" will match. You would have to do something like /(?!foo)...bar/ for that. We say "like" because there's the case of your "bar" not having three characters before it. You could cover that this way: /(?:(?!foo)...|^.{0,2})bar/. Sometimes it's still easier just to say: if (/bar/ && $` !~ /foo$/)
        Cheers,
        Shendal
Re: match and regex
by Zaxo (Archbishop) on Aug 13, 2002 at 19:42 UTC

    Do you mean next rather than last? Also, the OUT handle, while possible, looks fishy being read. A non-# character class will take care of the rest:

    while (<OUT>) { push(@hold1, $1) && next if (m/(\w+\.bld):\d+:[^#]*$/); } my $hold11 = join(' ', @hold1);

    After Compline,
    Zaxo

      thanks all :)
Re: match and regex
by thelenm (Vicar) on Aug 13, 2002 at 19:37 UTC
    It looks like you may want to use negative lookahead, something like this:
    while (<OUT>) { push(@hold1, $1) && last if (m/(\w+\.bld)(?!.*?#)/); } my $hold11 = join(' ', @hold1);
    This will only match if there is no "#" character in the string after ".bld".

    -- Mike

    --
    just,my${.02}

Re: match and regex
by fruiture (Curate) on Aug 13, 2002 at 19:34 UTC

    well, the 'bld' is anyways followed by a colon, digits, a colon and if the next character is a #, it should not match?

    Looks like m/(\w+\.bld):\d+:[^#]/ should work, or even m/(\w+\.bld)[^#]+$/. Does that cover all cases?

    update, forgot about [ ]

    --
    http://fruiture.de