The traditional way to change foo
to bar
in a string is to do this:
$string =~ s/foo/bar/;
This is all well and good, but what if foo
and bar
contain lots of /
characters? For example, what if you want to change all instances of http://
to https://
? You'd have to escape out the /
characters with \
, and so you'd see something like this:
$string =~ s/http:\/\//https:\/\//;
You have to admit that the above substitution is not easy on the eyes. It's not so easy to tell which /
belong to s///
and which belong to http://
. And the \
characters used to escape the /
characters just make the whole line more difficult to understand.
Some people call this "Leaning Toothpick Syndrome," because all the /
and \
characters look like leaning toothpicks.
The good news is that you're not required to use /
when using s///
. There are many other characters you can use instead, which make the following lines equivalent to the one above:
$string =~ s#http://#https://#;
$string =~ s@http://@https://@;
$string =~ s!http://!https://!;
$string =~ s|http://|https://|;
Because the regular expression delimiter is no longer the default /
, you no longer have to escape out the /
, making the whole line much easier to read.
You would have to escape out whichever delimiter you use, so to avoid "Leaning Toothpick Syndrome" I would advise using a delimiter that does not appear in your expression.
There are many characters you can use as delimiters; I won't list them here. However, there are four special bracket delimiters that come in pairs and surround your expressions, much like parentheses do. They are: (
and )
, [
and ]
, {
and }
, and finally, <
and >
. You use them like this:
$string =~ s(http://)(https://);
$string =~ s<foo><bar>g;
A bit easier to read without all those toothpicks, isn't it?
Your substitution expression will be easier to read if the delimiter you use doesn't exist in the expression itself. (Otherwise, you will have to escape it out with \
.)
What's a little strange with the example you gave:
$string =~ s<(\d+)><$1\.>g;
Is that there are no /
characters anywhere in the expression, so presumably it's not any clearer than:
$string =~ s/(\d+)/$1\./g;
However, maybe the original coder thought that the two \
characters would contrast with the /
characters, and so wanted to avoid the /
delimiters altogether.
Note: You didn't ask about this, but the $1\.
part of the substitution needlessly escapes out the .
character. You don't need the \
there, because the second part of a s///
substitution is not a regular expression -- it is only the replacement, and the .
is never used there to match a character. So there's no point in escaping it in your case, as .
always means a literal .
there.
So the above line would be better written as:
$string =~ s/(\d+)/$1./g;
I hope this helps!