Rationale: When people ask "How can I expand variables in text
strings?" what they are usually thinking is "How do I call Perl's
interpolation engine on a string?". The answer given in the current
version of the FAQ does not answer that question. Now if there were
no trivial answer to this question the FAQ could be forgiven for not
answering it. But there is a trivial answer so, IMHO, the FAQ should
give it.
The this patch adds the actual answer to the actual question into the
answer given in the FAQ.
The FAQ currently gives a solution using symrefs then goes on to say
it's probably not applicable. To avoid this answer becoming unduely
long the patch below removes that part.
I have also changed the question as most people looking for this
question using 'perldoc -q' would try 'perldoc -q interpolate' and
thus would not find the question with the current wording.
Since the patch actually almost completely replaces this entry FAQ
it's rather human-unreadable. I, therefore, show below what the
patched answer looks like:
How can I expand/interpolate variables in text strings?
To process a string through Perl's interpolation engine
simply:
$text = 'this has a $foo in it...\n ...and a $bar';
# Assume $text does not contain "\nEND\n"
chop ( $text = eval "<<END\n$text\nEND\n" );
die if $@;
This will not work, for good reason, if $text is tainted.
For an explanation of how $text could execute arbitrary
Perl see ``How do I expand function calls in a string?''
in this section of the FAQ.
If $text comes from a source external to the Perl script
(typically a file) and you trust executable code from that
source then simply untaint it. This is no more or less
dangerous than using "do()". For an explaination of
tainting see the perlsec manpage.
If you do not trust the source, you can limit and launder
the parts of $text that are passed to eval():
$text =~ s/(\$\w+)/$1/eeg; # needed /ee, not /e
This still gives unrestricted access to scalar variables.
It is often better to use a hash:
%user_defs = (
foo => 23,
bar => 19,
);
$text =~ s/\$(\w+)/$user_defs{$1}/g;
For other variations on the theme of text templates see
the sprintf() function and numerous modules on CPAN.
And here's the patch...
--- perl-5.8.1-RC4/pod/perlfaq4.pod Wed Jul 30 15:44:40 2003
+++ perlfaq4.pod Tue Aug 5 14:28:59 2003
@@ -554,6 +554,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">:
@@ -572,8 +575,8 @@
print "My sub returned @{[mysub(1,2,3)]} that time.\n";
-See also ``How can I expand variables in text strings?'' in this
-section of the FAQ.
+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?
@@ -921,25 +924,31 @@
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?
+=head2 How can I expand/interpolate variables in text strings?
-Let's assume that you have a string like:
+To process a string through Perl's interpolation engine simply:
- $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 = eval "<<END\n$text\nEND\n" );
+ die if $@;
-If those were both global variables, then this would
-suffice:
+This will not work, for good reason, if $text is tainted. For an
+explanation of how $text could execute arbitrary Perl see ``How do I
+expand function calls in a string?'' in this section of the FAQ.
- $text =~ s/\$(\w+)/${$1}/g; # no /e needed
+If $text comes from a source external to the Perl script (typically a
+file) and you trust executable code from that source then simply
+untaint it. This is no more or less dangerous than using C<do()>.
+For an explaination of tainting see L<perlsec>.
-But since they are probably lexicals, or at least, they could
-be, you'd have to do this:
+If you do not trust the source, you can limit and launder the parts of
+$text that are passed to eval():
- $text =~ s/(\$\w+)/$1/eeg;
- die if $@; # needed /ee, not /e
+ $text =~ s/(\$\w+)/$1/eeg; # 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 scalar variables. It is often
+better to use a hash:
%user_defs = (
foo => 23,
@@ -947,8 +956,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"?