in reply to Re^3: Slurping search-replace patterns from a file
in thread RESOLVED: Slurping search-replace patterns from a file

Hope I didn't miss anything...

That's the crucial point: You never know. Perl is a language with a very complex syntax (compared to all other programming languages that I know of) that you can basically never be sure if you approach things in this way.

I thought I was quite confident with Perl's syntax, until I found out that you can have whitespaces between the sigil and the variable, and that even works in string interpolation:

$ perl -wle 'my $x = 3; print "x: $ x"' x: 3

I certainly didn't expect that.

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?

Replies are listed 'Best First'.
Re^5: Slurping search-replace patterns from a file
by gone2015 (Deacon) on Oct 14, 2008 at 20:14 UTC
    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...

      Wow, that was clever but a bit beyond my needs. I ended up using the code you posted in your previous message and it's working perfectly.

      The possible security risks of some obscure escape circumvention are, for me, less important than the performance hit of manually storing and retrieving the backreferences.

      Thanks again.

      -HKS