Reputation: 12321
Is there a more elegant way of bringing a variable into a pattern than this (put the patterin in a string before instead of using it directly in //)??
my $z = "1"; # variable
my $x = "foo1bar";
my $pat = "^foo".$z."bar\$";
if ($x =~ /$pat/)
{
print "\nok\n";
}
Upvotes: 2
Views: 1959
Reputation: 66873
Need to delimit the variable's name so to be recognized inside a string, /^foo${z}bar$/
†
Use the qr
operator to build a variable with a regex pattern
my $pat = qr/^foo${z}bar$/;
If the delimiters are '
the variables aren't interpolated, just like for normal strings.
This operator is the best way to build patterns ahead of time as it builds a proper regex pattern, accepting everything that one can use in a pattern in a regex. It also takes modifiers, so for one the above can be written as
my $pat = qr/^foo $z bar$/x;
for a little extra clarity (but careful with omitting those {}
).†
The initial description from the above perlop
link (examples and discussion follow):
qr/STRING/msixpodualn
This operator quotes (and possibly compiles) its STRING as a regular expression. STRING is interpolated the same way as PATTERN in
m/PATTERN/
. If "'" is used as the delimiter, no variable interpolation is done. Returns a Perl value which may be used instead of the corresponding/STRING/msixpodualn
expression. The returned value is a normalized version of the original pattern. It magically differs from a string containing the same characters:ref(qr/x/)
returns "Regexp"; however, dereferencing it is not well defined (you currently get the normalized version of the original pattern, but this may change).
The same goes for normal strings, "^foo${z}\$"
, and most patterns work. But we often need to do more work since many regex patterns in a double-quoted string have their own meaning.
An example are escaped sequences, which are treated as string "escapes" and interpolated as such, or attempted (\s
, \w
... fail with warnings for not being recognized as valid escapes). As they need be passed to the regex untouched anyway most escapes need be escaped (\\w
), depriving \
of its special meaning -- but some (\x27
) need to stay as they are!
Single-quoting the string solves this (no need to escape things) but then variable interpolation is off. The qr
has none of these complications as it's meant for a regex pattern.
† Once a variable is getting interpolated it may be a good idea to escape special characters that may be hiding in it, that could throw off the regex, using quotemeta-based \Q ... \E
my $pat = qr/^foo \Q$z\E bar$/x;
If this is used then the variable name need not be delimited either
my $pat = qr/^foo\Q$z\Ebar$/;
Thanks to Håkon Hægland for bringing this up.
Upvotes: 7