After numerous heated debates on comp.lang.perl.* here is my new
improved answer for perlfaq4: expanding variables in strings.
--- perlfaq4.pod Thu Mar 6 18:03:55 2003
+++ perlfaq4-bam.pod Thu Mar 6 18:28:36 2003
@@ -539,6 +539,9 @@
This won't expand C<"\n"> or C<"\t"> or any other special escapes.
+See also ``How can I expand/interpolate variables in text strings?'' in this
+section of the FAQ.
+
=head2 How do I remove consecutive pairs of characters?
To turn C<"abbcccd"> into C<"abccd">:
@@ -565,7 +568,7 @@
Version 5.004 of Perl had a bug that gave list context to the
expression in C<${...}>, but this is fixed in version 5.005.
-See also ``How can I expand variables in text strings?'' in this
+See also ``How can I expand/interpolate variables in text strings?'' in this
section of the FAQ.
=head2 How do I find matching/nesting anything?
@@ -898,25 +901,26 @@
If Text::Soundex does not do what you are looking for, you might want
to consider the String::Approx module available at CPAN.
-=head2 How can I expand variables in text strings?
-
-Let's assume that you have a string like:
+=head2 How can I expand/interpolate variables in text strings?
- $text = 'this has a $foo in it and a $bar';
+ $text = 'this has a $foo in it...\n ...and a $bar';
+ # Assume $text does not contain "\nEND\n"
+ chop ( $text = chop "<<END\n$text\nEND\n" );
+ die if $@;
-If those were both global variables, then this would
-suffice:
+This is dangerous if the text comes form an untrusted source,
+consider:
- $text =~ s/\$(\w+)/${$1}/g; # no /e needed
+ $text = '@{[ system "rm -rf /" ]}';
-But since they are probably lexicals, or at least, they could
-be, you'd have to do this:
+If you only need to process simple scalars then you can do limit the
+parts of the string that are passed to eval() like this:
$text =~ s/(\$\w+)/$1/eeg;
die if $@; # needed /ee, not /e
-It's probably better in the general case to treat those
-variables as entries in some special hash. For example:
+This still gives unrestricted access to your scalar variables. It is
+often better to use a hash:
%user_defs = (
foo => 23,
@@ -924,8 +928,8 @@
);
$text =~ s/\$(\w+)/$user_defs{$1}/g;
-See also ``How do I expand function calls in a string?'' in this section
-of the FAQ.
+For other variations on the theme of text templates see the sprintf()
+function and numerous modules on CPAN.
=head2 What's wrong with always quoting "$vars"?