You’ve read in a string with an embedded variable reference, such as:
You owe $debt to me.
Now you want to replace $debt
in the string with
its value.
Use a substitution with symbolic references if the variables are all globals:
$text =~ s/\$(\w+)/${$1}/g;
But use a double /ee
if they might be lexical
(my
) variables:
$text =~ s/(\$\w+)/$1/gee;
The first technique is basically “find what looks like a
variable name, and then use symbolic dereferencing to interpolate its
contents.” If $1
contains the string
somevar
, then ${$1}
will be
whatever $somevar
contains. This won’t work
if the use
strict
'refs'
pragma is in effect because
that bans symbolic dereferencing.
Here’s an example:
use vars qw($rows $cols);
no strict 'refs'; # for ${$1}/g below
my $text;
($rows, $cols) = (24, 80);
$text = q(I am $rows high and $cols long); # like single quotes!
$text =~ s/\$(\w+)/${$1}/g;
print $text;
I am 24 high and 80 long
You may have seen the /e
substitution modifier used to evaluate
the replacement as code rather than as a string. It’s designed
for situations such as doubling every whole number in a string:
$text = "I am 17 years old"; $text =~ s/(\d+)/2 * $1/eg;
When Perl is compiling your program and sees a /e
on a substitute, it compiles the code in the replacement block along
with the rest of your program, long before the substitution actually
happens. When a substitution is made, $1
is
replaced with the string that matched. The code to evaluate would
then be something like:
2 * 17
If we tried saying:
$text = 'I am $AGE years old'; # note single quotes $text =~ s/(\$\w+)/$1/eg; # WRONG
assuming $text
held a mention of the variable
$AGE
, Perl would dutifully replace
$1
with $AGE
and then evaluate
code that looked like:
'$AGE'
which just yields us our original string back again. We need to
evaluate the result again to get the value of
the variable. To do that, just add another /e
:
$text =~ s/(\$\w+)/$1/eeg; # finds my() variables
Yes, you can have as many /e
modifiers as
you’d like. Only the first one is compiled and syntax-checked
with the rest of your program. This makes it work like the
eval
{BLOCK}
construct, except that it doesn’t trap exceptions. Think of it
more as a do
{BLOCK}
instead.
Subsequent /e
modifiers are quite different.
They’re more like the eval
"STRING
" construct. They don’t get compiled
until run-time. A small advantage of this scheme is that it
doesn’t make you put a no
strict
'refs'
pragma in the block. A tremendous advantage is that unlike the
symbolic dereferencing, this mechanism can actually find lexical
variables created with my
, something symbolic
references can never do.
The following example uses the
/x
modifier to
enable whitespace and comments in the pattern part of the substitute
and /e
to evaluate the right-hand side as code.
The /e
modifier gives you more control over what
happens in case of error or other extenuating circumstances, as we
have here:
# expand variables in $text, but put an error message in # if the variable isn't defined $text =~ s{ \$ # find a literal dollar sign (\w+) # find a "word" and store it in $1 }{ no strict 'refs'; # for $$1 below if (defined $$1) { $$1; # expand global variables only } else { "[NO VARIABLE: \$$1]"; # error msg } }egx;
Note that the syntax of $$1
has changed for Perl
5.004: it used to mean ${$}1
but now means
${$1}
. For backwards compatibility, in strings it
still takes the old meaning (but generates a warning with -w). People will write
${$1}
within a string to keep from dereferencing
the PID variable. If $$
were 23448, then
$$1
in a string would turn into
234481
, not the contents of the variable whose
name was stored in $1
.
The s///
operator in perlre
(1) and perlop(1) and the
“Pattern Matching” and “Regular Expressions”
sections of Chapter 2 of Programming Perl;
the eval
function in perlfunc(1) and Chapter 3 of Programming Perl
; the similar use of substitutions in Section 20.9.
Get Perl Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.