views:

114

answers:

3

Perl's quotemeta operator typically works on the SEARCH side of s///, but in generating code to be compiled with eval, how should I protect the REPLACEMENT that should be used literally but may contain bits such as $1?

With code of the form

my $replace = quotemeta $literal_replacement;

my $code = eval <<EOCode;
  sub { s/.../$replace/ }
EOCode

when will it produce syntax errors or surprising results?

+7  A: 

As far as I can tell, perl doesn't do magic things with $replace as long as you don't add the /e flag on the substitute. So quotemeta will always change your result, as it then contains a lot of backslashes.

#!/usr/bin/perl

$test="test";

$literal_replacement='Hello $1, or \1';
my $replace = quotemeta $literal_replacement;
$test =~ s/test/$replace/;

print $test,"\n";

returns:

Hello\ \$1\,\ or\ \\1

Which is probably not what you want :

Sec
Thanks for your answer. I asked my question poorly, leaving out important context. Please see the updated question.
Greg Bacon
+1  A: 

The replacement side is a normal interpolating string (unless you start adding /e modifiers, in which case it becomes as many string evals as there are /e modifiers.). Perl 5 does not care what is in the variable you interpolate into the string. It is the same as:

my $foo = 5;
my $bar = '$foo';
my $baz = "$foo $bar"; 
print "$baz\n"; #this is 5 $foo not 5 5
Chas. Owens
Thanks for your answer. I asked my question poorly, leaving out important context. Please see the updated question.
Greg Bacon
+1  A: 

The replacement is usually processed like a double-quoted string, but you can change that by using single-quotes as the delimiter:

$test =~ s<test>'$replace';
Alan Moore
Thanks for your answer. I asked my question poorly, leaving out important context. Please see the updated question.
Greg Bacon
I don't think I can help you there. I can't even imagine why you would want to do that.
Alan Moore