Delayed String Interpolation (aka, always check the FAQ)

stu42j on 2007-06-01T03:25:09

I was trying to fix some code today that was attempting to do delayed string interpolation. Something like:

$str = 'Foo: $foo';  # Actually defined in a config file.
$foo = 'bar';  # ...later

print eval("\$str"), "\n";


Except that just gives you:

Foo: $foo


My first thought was to check the FAQ but then, no, I think I've seen something like this in the eval doc. No, that's not helpful. Oops, gotta catch the bus...

Then I figure I'd take a shot at it before bed. I give Google a try but the closest hits are on Ruby. After an a-ha moment I came up with this:

print eval(qq{"$str"}), "\n";


Which works. But then as I start writing this post, I figure I'd better check the FAQ before I sound like an idiot. Yes, it is in the FAQ although my solution seems much simpler. Am I overlooking any problems with my solution?

Here's what the FAQ suggests:

eval { $text =~ s/(\$\w+)/$1/eeg };
die if $@;


asdlfkjhasdglk

educated_foo on 2007-06-01T04:23:39

It's not hard to defeat your quoting (if you care about malicious users):

$str = '", print(qq!you lose\n!),"'
eval(qq{"$str"})
# you lose

Re:asdlfkjhasdglk

Aristotle on 2007-06-01T07:08:57

eval qq{"\Q$str\E"}

Re:asdlfkjhasdglk

educated_foo on 2007-06-01T12:53:12

Right you are.

Re:asdlfkjhasdglk

stu42j on 2007-06-01T13:54:38

Well, that fixes the malicious entry problem but it also defeats the original purpose. The \Q\E prevents the string from ever getting interpolated and you are back to 'Foo: $bar'.

Re:asdlfkjhasdglk

stu42j on 2007-06-01T13:55:33

In this case, the string is safe but thanks for the warning.