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

Non-greedy match end of line bug?

by am12345 (Novice)
on Oct 26, 2021 at 01:08 UTC ( [id://11138035]=perlquestion: print w/replies, xml ) Need Help??

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

Should not \n be included in the match in both cases? What am I missing here?
$ perl -e '$_="foo\nbar"; print "1=|$1|\n" if m/(fo.+?)$/s' 1=|foo bar| $ perl -e '$_="foo\n"; print "1=|$1|\n" if m/(fo.+?)$/s' 1=|foo|

Replies are listed 'Best First'.
Re: Non-greedy match end of line bug?
by Fletch (Bishop) on Oct 26, 2021 at 01:31 UTC

    So reading perlre, a $ matches:

    • at the end of the string (your first case)
    • or before newline at the end of the string (what happens in your second case, leaving the newline out of $1)
    • before any newline if you've used /m

    If you use (say) Regexp::Debugger it might help stepping through and watching.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

      Well... I would buy it "by default" or with /m qualifier, but I did add a /s qualifier. And with that I think \n is supposed to be treated just like any other character. Should it not?
      s Treat string as single line. That is, change "." to match any character whatsoever, even a newline, which normally it would not match.

        You're not taking into account the non-greediness. To accommodate matching the $ (which is before the newline) $1 holds 'foo'. If you also want to match the terminal newline, use \z instead of $:

        $ perl -e '$_="foo\n"; print "1=|$1|\n" if m/(fo.+?)$/s' 1=|foo| $ perl -e '$_="foo\n"; print "1=|$1|\n" if m/(fo.+?)\z/s' 1=|foo |

        Your comparison with the first one-liner is not comparing apples with apples:

        $ perl -e '$_="foo\nbar"; print "1=|$1|\n" if m/(fo.+?)$/s' 1=|foo bar| $ perl -e '$_="foo\nbar\n"; print "1=|$1|\n" if m/(fo.+?)$/s' 1=|foo bar| $ perl -e '$_="foo\nbar\n"; print "1=|$1|\n" if m/(fo.+?)\z/s' 1=|foo bar |

        I also second ++Fletch's recommendation to use Regexp::Debugger. This allows you to step through the matching process and see exactly what's happening. I often use it myself.

        — Ken

Re: Non-greedy match end of line bug?
by ikegami (Patriarch) on Oct 26, 2021 at 14:43 UTC

    From the title and body, it's possible you think greediness (or non-greediness) can affect *if* a match occurs, but that's not the case.

    (In retrospect, you might already realize that. If so, just ignore this.)

Re: Non-greedy match end of line bug?
by LanX (Saint) on Oct 26, 2021 at 15:08 UTC
    > Should not \n be included in the match in both cases? What am I missing here?

    the $ is not inside your $1 group, so why should \n be included in the second print?

    anyway $ is a zero-length assertion

    never mind, fletch already gave the perfect answer.

    • "before newline at the end of the string"

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others learning in the Monastery: (7)
As of 2024-04-16 18:02 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found