What I learned from this is to never assume that you know every detail of Perl syntax, so I won't be sure that I've covered all corner cases. Can you be?
I would not presume.
AFAIK the only characters that trigger interpolation are '$' and '@'. But, as you say, with Perl it's unsafe to assume that anything can be depended on.
However, if we can trust that much, then escaping '$' unless it's followed by a digit only lets past stuff which is supposed to be safe. And escaping '@' unconditionally seems to cover that. Unless there's some other magic that throws the escaping mechansm.
<sigh>
I suppose one could fall back on a hand affair:
use strict ;
use warnings ;
while (<DATA>) {
my ($pat, $repl) = (split '/') [1, 2];
my $s = "foo" ;
printf "%40s '%s' -> ", "/$pat/$repl/", $s ;
my @trap = $s =~ m/$pat/ ;
$repl =~ s/(?<!\\)((?:\\\\)*)\$([1-9])/(defined($1) ? $1 : '')
.(defined($trap[$2-1]) ? $tra
+p[$2-1] : '')/eg ;
$s =~ s/$pat/$repl/ ;
print "'$s'\n" ;
}
__DATA__
s/foo/bar/
s/(fo)o/bar$1/
s/(fo)o/bar\$1/
s/(fo)o/bar\\$1/
s/oo/${system "echo hello sailor !"}/
s/oo/@{system "echo hello sailor !"}/
which only attempts to simulate '$1'..'$9' -- but that may be sufficient. Of course, String::Interpolate may well do a more complete job.
Unless, of course, there's some other gotcha...
|