tags:

views:

90

answers:

4

I seem to remember that there were certain conditions under which $ would match a newline (not "just before"), but I can't find anything in the docs that would confirm that. Did that use to be true in an earlier version of Perl or am I dreaming?

+3  A: 

If you pass the /s modifier to a regexp, then $ matches the end of the string and allows . to match \n.

This can be a bit confusing. For a string of foo\n, observe the difference between:

/.$/ # matches 'o'

/.$/s # still matches 'o'

/.+$/s # matches 'foo\n'

/.\z/ # doesn't match at all

/.\z/s # matches '\n'

szbalint
Sorry... not relevant to my question
JoelFan
Unless I'm misunderstanding something, you don't mean what you think you mean. `$` doesn't do any character matching, it does positional matching, so the question you might be asking is whether `$` matches before or after the newline.
szbalint
I remember something about it consuming the newline itself
JoelFan
@JoelFan => `$` is a zero width positional assertion, it never consumes any characters
Eric Strom
It's `/m` that changes the meaning of the anchors (`^` and `$`); `/s` only changes the meaning of the dot. `$` *always* matches at the end of the string or before a newline at the end of the string. In `/m` mode it also matches before any *other* newline. At least, that's how it works in Perl; there could be Perl-derived flavors that don't work exactly like Perl in that regard, but I can't think of any offhand.
Alan Moore
+5  A: 

That has always been the case. See perldoc perlreref ($ is an anchor):

$ Match string end (or line, if /m is used) or before newline

You should use \z if you want to match the end of the string:

\z Match absolute string end

Sinan Ünür
Yes. `"123\n" =~ /^\d+$/` is true. Which means all sorts of potential fun for your validation code if you get it wrong. :)
fennec
+3  A: 

You are confusing two very similar things. The $ matches at the end of a string if /m is not used, and at the end of a string or at the end of a string except for a final newline if /m is used. However, it does not actually match (consume) the newline itself. You could still match the newline character itself with something else in the regexp, for instance \n; or, if you also use /s, then /blah$./sm would theoretically match "blah\n" even though the $ is not the last thing in the regex.

(The reason this doesn't actually work is that both $. and $\ are actually interpreted as special variables instead of as $ plus ., so it is actually quite hard to put something after a $ in a regexp. Confusing, isn't it?)

Kilian Foth
I guess you could use $ . if you had /x
JoelFan
Not quite right. "at the end of a string or before a newline at the end of a string" if no /m, "at the end of a string or before any newline" if /m. Just "the end of the string" is \z.
ysth
To use $ anywhere in a regex, without /m you can just say \Z (not \z). With /m, you can stick `$` in a `$dollar` variable and interpolate that (as `${dollar}` if needed). Or do e.g. `/@{['$']}./`
ysth
+1  A: 

Adding the 'm' modifier, '$' will match (but not consume) end of line characters. Normally '$' matches end of string.

my $sample = "first\nsecond\nthird";
$sample =~ s/$/END/mg;
print $sample;

Produces:

firstEND
secondEND
thirdEND

If you want to consume the newline, just use the \n escape character:

my $sample = "first\nsecond\nthird";
$sample =~ s/\n/END/g;
print $sample;

Now you get:

firstENDsecondENDthird

Note that the 'm' modifier also affects '^' in the same way as '$'.

Jeff