if ($a =~ m!^$var/!)
$var
is a key in a two dimensional hash and $a
is a key in another hash.
What is the meaning of this expressions?
if ($a =~ m!^$var/!)
$var
is a key in a two dimensional hash and $a
is a key in another hash.
What is the meaning of this expressions?
This is a regular expression ("regex"), where the !
character is used as the delimiter for the pattern that is to be matched in the string that it binds to via the =~
operator (the $a
† here).
It may clear it up to consider the same regex with the usual delimiter instead, $a =~ /^$var\//
(then m
may be omitted); but now any /
used in the pattern clearly must be escaped. To avoid that unsightly and noisy \/
combo one often uses another character for the delimiter, as nearly any character may be used (my favorite is the curlies, m{^$var/}
). ‡ §
This regex in the question tests whether the value in the variable $a
begins with (by ^
anchor) the value of the variable $var
followed by /
(variables are evaluated and the result used). §
† Not a good choice for a variable name since $a
and $b
are used by the builtin sort
‡ With the pattern prepared ahead of time the delimiter isn't even needed
my $re = qr{^$var/};
if ($string =~ $re) ...
(but I do like to still use //
then, finding it clearer altogether)
Above I use qr but a simple q()
would work just fine (while I absolutely recommend qr
). These take nearly any characters for the delimiter, as well.
§ Inside a pattern the evaluated variables are used as regex patterns, what is wrong in general (when this is intended they should be compiled using qr
and thus used as subpatterns).
An unimaginative example: a variable $var = q(\s)
(literal backslash followed by letter s
) evaluated inside a pattern yields the \s
sequence which is then treated as a regex pattern, for whitespace. (Presumably unintended; we just wanted \
and s
.)
This is remedied by using quotemeta, /\Q$var\E/
, so that possible metacharacters in $var
are escaped; this results in the correct pattern for the literal characters, \\s
. So a correct way to write the pattern is m{^\Q$var\E/}
.
Failure to do this also allows the injection bug. Thanks to ikegami for commenting on this.
The match operator (m/.../
) is one of Perl's "quote-like" operators. The standard usage is to use slashes before and after the regex that goes in the middle of the operator (and if you use slashes, then you can omit the m
from the start of the operator). But if the regex itself contains a slash then it is convenient to use a different delimiter instead to avoid having to escape the embedded slash. In your example, the author has decided to use exclamation marks, but any non-whitespace character can be used.
Many Perl operators work like this - m/.../
, s/.../.../
, tr/.../.../
, q/.../
, qq/.../
, qr/.../
, qw/.../
, qx/.../
(I've probably forgotten some).