Here we go again...
Please someone, just apply this patch.
It may not be perfect but it's still a couple of orders of magnitude
better than what's there now! Not least because, unlike the current
version, it actually answers the question that is really in the mind
of most people who frequently ask this question.
If someone wants to improve further then let them submit another
patch. Please do not delay this long-over-due correction by straining
over every word.
--- perlfaq4.pod Wed Mar 12 19:55:30 2003
+++ perlfaq4-bam.pod Wed Mar 12 21:36:30 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">:
@@ -557,16 +560,8 @@
print "My sub returned @{[mysub(1,2,3)]} that time.\n";
-If you prefer scalar context, similar chicanery is also useful for
-arbitrary expressions:
-
- print "That yields ${\($n + 5)} widgets\n";
-
-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
-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?
@@ -898,25 +893,35 @@
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:
-
- $text = 'this has a $foo in it and a $bar';
-
-If those were both global variables, then this would
-suffice:
+=head2 How can I expand/interpolate variables in text strings?
- $text =~ s/\$(\w+)/${$1}/g; # no /e needed
+You can process a string through Perl's interpolation engine like
+this:
-But since they are probably lexicals, or at least, they could
-be, you'd have to do this:
+ $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, and for good reason, if $text is coming form
+an tainted source. For explanation of how $text could execute
+arbitrary Perl code see ``How do I expand function calls in a
+string?'' in this section of the FAQ.
+
+If $text is coming from a source external to the Perl script
+(typically a file) and you would be content to trust executable code
+from that source then you simply make data from that source untainted.
+This is no more or less dangerous than using C<do()>. For an
+explaination of tainting see L<perlsec>.
+
+If you do not trust the source that much then you can limit and
+launder the parts of the string that are passed to eval() something
+like this:
- $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 your scalar variables. It is
+often better to use a hash:
%user_defs = (
foo => 23,
@@ -924,8 +929,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"?