How to use a variable in the replacement side of the Perl substitution operator?

Manu picture Manu · Dec 25, 2008 · Viewed 104.3k times · Source

I would like to do the following:

$find="start (.*) end";
$replace="foo \1 bar";

$var = "start middle end";
$var =~ s/$find/$replace/;

I would expect $var to contain "foo middle bar", but it does not work. Neither does:

$replace='foo \1 bar';

Somehow I am missing something regarding the escaping.


I fixed the missing 's'

Answer

ysth picture ysth · Dec 25, 2008

On the replacement side, you must use $1, not \1.

And you can only do what you want by making replace an evalable expression that gives the result you want and telling s/// to eval it with the /ee modifier like so:

$find="start (.*) end";
$replace='"foo $1 bar"';

$var = "start middle end";
$var =~ s/$find/$replace/ee;

print "var: $var\n";

To see why the "" and double /e are needed, see the effect of the double eval here:

$ perl
$foo = "middle";
$replace='"foo $foo bar"';
print eval('$replace'), "\n";
print eval(eval('$replace')), "\n";
__END__
"foo $foo bar"
foo middle bar

(Though as ikegami notes, a single /e or the first /e of a double e isn't really an eval(); rather, it tells the compiler that the substitution is code to compile, not a string. Nonetheless, eval(eval(...)) still demonstrates why you need to do what you need to do to get /ee to work as desired.)