in reply to Re: Re: $1 in variable regex replacement string
in thread $1 in variable regex replacement string

# used by munge function to safely interpolate # $1, $2 etc into the replacement string sub _safeswitch { my @P = (undef,$1,$2,$3,$4,$5,$6,$7,$8,$9); $_[0] =~ s/\$(\d)/$P[$1]/g; $_[0]; }

If I read the above correctly, it'll only handle 9 sets of capturing parens, and it's possible that we may have matched more than 9 sets.

My fix is to dynamically build @P to size.

# used by munge function to safely interpolate # $1, $2, etc. into the replacement string sub _safeswitch { my %seen; @seen{@+} = (undef) x @+; my @P; { no strict 'refs'; # allow $$_ to be $1, $2, etc. no warnings 'unitialized'; # allow undef as $$_ @P = map { $$_ } undef, 1 .. scalar keys %seen; } $_[0] =~ s/\$(\d+)/$P[$1]/g; $_[0]; }

And a test:

#!/usr/bin/perl use strict; use warnings; my $str = 'abcdefghijklmnopqrstuvwxyz'; my $pat = '(.).(.).(.)..(.).(.)(.)(.).(.)(.)(.).(.)(.)(.)(.).+'; my $repl = '$5$14$12$13 $1$8$9$13$4$3$11 $10$3$11$7 $4$1$2$6$3$11'; print munge( $str, $pat, $repl ), "\n"; sub munge { my($str, $pat, $repl) = @_; $str =~ s/$pat/_safeswitch($repl)/eg; return $str; } # used by munge function to safely interpolate # $1, $2, etc. into the replacement string sub _safeswitch { my %seen; @seen{@+} = (undef) x @+; my @P; { no strict 'refs'; # allow $$_ to be $1, $2, etc. no warnings 'uninitialized'; # allow undef as $$_ @P = map { $$_ } undef, 1 .. scalar keys %seen; } $_[0] =~ s/\$(\d+)/$P[$1]/g; $_[0]; } exit;
UPDATE

Incidentally, the line @seen{@+} = (undef) x @+; is a faster way to build
such a hash than the various equivalents ( %seen = map { $_ => undef } @+;
most notable among them for being popular and 4x slower).

I discovered this just today ;)

blyman
setenv EXINIT 'set noai ts=2'

Replies are listed 'Best First'.
Re: $1 in variable regex replacement string
by tadman (Prior) on Feb 14, 2003 at 03:26 UTC
    I'm not sure why you're using a hash there when this should do the trick:
    sub safeswitch { no strict 'refs'; my @P = map { $$_ } 0..@+; $_[0] =~ s/\$(\d+)/$P[$1]/g; $_[0]; }
    As far as I can tell, you're only using %seen to count?
      Good point. I originally wrote it using a hash, then a few minutes later discovered almost the exact same thing when I followed jsprat's link in this node. I thought about updating my code, but then decided it was buried so deep nobody would find it anyway ;)

      blyman
      setenv EXINIT 'set noai ts=2'