in reply to s/// in a sub : passing expressions

Juerd explained how to do this with eval, but there is another way. I saw this illustrated in a node a couple of months back, which of course I can no longer find, so I'll try to reproduce the concept. Basically the idea is that we build an array of the $1 .. $n values then do a second substitution on that. The array is required because the substitution clobbers the variables:
sub dyn_replace { my ($replace) = @_; my @groups; { no strict 'refs'; $groups[$_] = $$_ for 1 .. $#-; # the size of @- tells us the + number of capturing groups } $replace =~ s/\$(\d+)/$groups[$1]/g; return $replace; }
and we use it as follows
my $pat = qr/foo(\d+)bar(\d+)/; my $rep = 'x$1y$2'; my $str = 'foo36bar47'; $str =~ s/$pat/dyn_replace($rep)/e; print "$str\n";
and it prints "x36y47", just as desired.

Replies are listed 'Best First'.
Re^2: s/// in a sub : passing expressions
by Tanktalus (Canon) on Oct 30, 2005 at 01:29 UTC

    I think you're referring to an old node of mine: Re: How to do regex backreferences within $variable replacement text?. When I used that solution at work, another perl programmer told me I was "too advanced." I don't think that this was very advanced - just a novel way of looking at the problem.

    Anyway, that entire thread may be relevant here.

      Yes, that's the one. Your solution is neater than mine because it avoids the number variables, and possibly faster (though I can't be bothered to benchmark it), but mine has a small advantage in that you can use it with modifiers such as /i, /g, and /x.