in reply to Regex not matching closing newline?

$ is a zero-width assertion that matches at the end of the string, or just before the newline at the end of the string (note its behavior can be changed by the /m modifier). ? makes the preceding .* non-greedy, so that it allows $ to match just before the newline, while a normal .* is greedy, causing it to gobble up everything it can, and the $ matches just after the newline. Note that since you're using the /s modifier, the dot . can also match a newline, which it normally does not.

What is your desired behavior? If you want the match to always include the newline, I'd be specific about it: /ab.*\n/, or, if you want the newline to be optional (e.g. the last line in a file may not have a newline), then I'd probably write /ab.*(?:\z|\n)/. If you want the match to always exclude the newline, I'd leave off the /s modifier, or be specific about what you want to match by saying e.g. [^\n]* or \N*.

Replies are listed 'Best First'.
Re^2: Regex not matching closing newline?
by rverscho (Initiate) on Jan 11, 2019 at 09:54 UTC
    Thanks. The \n must be included, so the greedy variant must be used.
    I have been using Perl for so many years, but it is a scary thought that I seem to have missed the part that says "or just before the newline at the end of the string".
    --need to urgently check some existing code now--

      \z, as proposed by haukex might be the most appropriate solution: it only matches at the absolute end of the string, so both greedy and non greedy variants do what you want.

      $p = substr($s, @-[1], (@+[1] - @-[1])); is a strange way to write $p = $1; you know you can access captures with $X with X the number of the of the capture right?

      Also, rather than trying to make your output more explicit with enclosing [ and string length, I strongly advise you to use Data::Dump (or the Core Data::Dumper, but you have to set $Data::Dumper::useqq = 1; for the more explicit version) for debugging (it will take care or invisible, or look-alike characters for you, and works well with refs and structures)

      use Data::Dump 'pp'; $s = "abc\n"; if ($s =~ /(ab.*?)\z/s) { pp($1); } if ($s =~ /(ab.*)\z/s) { pp($1); } __END__ "abc\n" "abc\n"