regexperlsubstitution

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


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.


Solution

  • 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.)