http://www.perlmonks.org?node_id=1015592

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

Dear Monks,

perlre says this:

(??{ code })

This is a "postponed" regular subexpression. The code is evaluated at run time, at the moment this subexpression may match. **The result of evaluation is considered a regular expression and matched as if it were inserted instead of this construct.**

Then perlre says:

Note that this means that the contents of capture groups defined inside an eval'ed pattern are not available outside of the pattern...

...Thus,

('a' x 100)=~/(??{'(.)' x 100})/

will match, it will not set $1.

Huh? I checked, and in fact $1 is not set. So in my opinion, the last quoted line should say:

Despite the regex insertion, *confoundingly* the capture groups inside this construct are not available after the insertion.

In other words, I don't see how by inserting the resulting regex instead of this construct it follows that the capture groups in the regex won't be available, which perlre seems to think is self-evident.

Replies are listed 'Best First'.
Re: Evaluating code in a regex at runtime: (??{...})
by dave_the_m (Monsignor) on Jan 28, 2013 at 01:12 UTC
    When a pattern is compiled, all the captures are allocated fixed indices: so for example when the following pattern is compiled, the indices shown are assigned.
    /(....)...(...)...(??{foo()})....(...)/ ^ ^ ^ 1 2 3
    In particular, the last capture is index number 3.

    Each time the pattern is run, foo() might return a string or qr// which has a different number of captures; and which might recursively also include /(??{...})/ and further nested captures. This would make it nearly impossible to guess how to refer to the final capture in the outer pattern, unless we just always call it $3.

    Dave.

Re: Evaluating code in a regex at runtime: (??{...})
by Athanasius (Archbishop) on Jan 28, 2013 at 02:33 UTC

    Note that the contents of the match are still accessible via a named capture group:

    #! perl use Modern::Perl; ('a' x 100) =~ /(?<match>(??{'(.)' x 100}))/; say $+{match};

    Output:

    12:28 >perl 504_SoPW.pl aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 12:28 >

    See Capture groups.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      > Note that the contents of the match are still accessible via a named capture group:

      > ...  ('a' x 100) =~ /(?<match>(??{'(.)' x 100}))/;

      ehm ... what you're showing also works with unnamed capture groups:

      DB<113> ('a' x 10) =~ /((??{'(.)' x 10}))/; print "<$1>" => 1 <aaaaaaaaaa>

      The OP's point was about dynamically generated capture groups, but yours is outside the embedded Perl code.

      Cheers Rolf

        Yes, you’re right. So in dave_the_m’s example, all we need to do is add another set of parentheses:

        /(....)...(...)...((??{foo()}))....(...)/ ^ ^ ^ ^ 1 2 3 4

        and the dynamically generated capture group is assigned to $3. For example:

        use Modern::Perl; my $str = 'abcd$$$$$ef'; my @caps = $str =~ /(a)b(c)d((??{'(.)' x 5}))e(f)/; say join(', ', @caps);

        Output:

        18:33 >perl 504_SoPW.pl a, c, $$$$$, f 18:38 >

        What we (apparently) can’t get is multiple capture groups matches assigned to different capture groups (whether named or unnamed) from the same dynamic match. Correct?

        Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: Evaluating code in a regex at runtime: (??{...})
by Kenosis (Priest) on Jan 28, 2013 at 00:15 UTC

    Deleted... Misunderstood the issue...