sleepingsquirrel has asked for the wisdom of the Perl Monks concerning the following question:

I was wondering if there was an easy way of stuffing the capturing variables ($1, $2, etc) into an array which could be accessed from the replacement portion of the s/// operator (so you could do a foreach, etc. on them). You could always do something like...
s/$regex/@a=($1, $2, $3).../e;
but if the regex is program generated then you have to create another string with the proper number of terms in it and eval it (or I suppose you could do something like @a=(\$1,\$2,...,\$100) before-hand an pray you never get more capturing parentheses). I'm sure it's possible to gin up something using @-,@+, and substr, but I'm thinking that there is probably a better, more DWIM path to enlightnment.

Replies are listed 'Best First'.
Re: Array of ($1, $2, ...) in replacement part of s///?
by ysth (Canon) on Jan 28, 2004 at 19:51 UTC
    Nope, @-, @+, and substr is the way. People periodically suggest a @& variable to do what you want, but that would invoke all the drawbacks of $&.

    One handy feature is that when you say $s =~ s/re/expr/ge within expr, $s will be the original $s and the offsets in @- and @+ will be offsets into the original $s, even if earlier matches changed the length of $s.

    Would be nice if $& (and the vaporware @&) were usable in the substitution part of s/// without penalty...

      Wow, I learn something new about perl every day.

      from perlvar:

      After a match against some variable $var: $` is the same as substr($var, 0, $-[0]) $& is the same as substr($var, $-[0], $+[0] - $-[0]) $' is the same as substr($var, $+[0]) $1 is the same as substr($var, $-[1], $+[1] - $-[1]) $2 is the same as substr($var, $-[2], $+[2] - $-[2]) $3 is the same as substr $var, $-[3], $+[3] - $-[3])
      so I wrote a test case:
      use strict; for my $regex (qr/(.)oo(.)ar(.)az/, qr/fo(.)barba(.)/) { my $str = "foobarbaz"; $str =~ s/$regex/ my @a; for my $index (1 .. $#+) { push @a, substr($str, $-[$index], $+[$index] - $-[$index]) +; } join "," , @a; /e; print "$str\n"; }
      outputs
      f,b,b o,z
      I'll have to remmember that one.

      --

      flounder

        And now in the usual idiom as well.

        join "," , map substr( $str, $-[$_], $+[$_] - $-[$_] ), 1 .. $#+;
Re: Array of ($1, $2, ...) in replacement part of s///?
by hardburn (Abbot) on Jan 28, 2004 at 19:42 UTC

    When you do a simple match, you can assign the captured portions to an array like this:

    my $str = "foobarbaz"; my @a = $str =~ /(.)oo(.)ar(.)az/; local $, = ", "; print @a; __OUTPUT__ f, b, b

    Given that, you can wrap the match in a qr// and run it twice:

    my $regex = qr/(.)oo(.)ar(.)az/; my $str = "foobarbaz"; my @a = $str =~ $regex; $str =~ s/$regex/$3$2$1/; local $, = ", "; print $str, @a; __OUTPUT__ bbf, f, b, b

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    : () { :|:& };:

    Note: All code is untested, unless otherwise stated

Re: Array of ($1, $2, ...) in replacement part of s///?
by BrowserUk (Patriarch) on Jan 28, 2004 at 21:06 UTC

    You can use the code assertion regex to do this. (See perlre "Extended patterns" for details).

    P:\test>perl -Mstrict -wle" my $s = 'the quick brown fox jumps over the lazy dog'; my @bits; $s =~ s[ .(.)(?{ push@bits,$^N }) ..(..)(?{ push@bits,$^N }) .] [ print join'-',@bits; ]gex;" h-qu h-qu-k-ro h-qu-k-ro- -x h-qu-k-ro- -x -m- o h-qu-k-ro- -x -m- o-r-he h-qu-k-ro- -x -m- o-r-he-a- d

    Note: I've split the 'one-liner' up to avoid the code wrap mangler.


    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    Timing (and a little luck) are everything!

      This just might be the excuse I was looking for to use the (?{}) construct and friends. But I notice that perlre says...
      WARNING: This extended regular expression feature is considered highly experimental, and may be changed or deleted without notice.
      But there is nary a word about this experimentalism in my 3rd edition Camel. Anyone care to take a guess about its life expectancy? (5.10?, ponie?, 6.0?)
        There may (should) be change in how those constructs interact with lexicals in the code. Otherwise, they aren't going away in any version of perl5.