in reply to Using a capture in /(?{...})/

I found something that does work: pos (and $+[0]). Actually, argless pos works even if we're not operating on $_!

Therefore, this hack works:

use strict; use warnings; my $re0; my $re1; our $s_pos; $re1 = qr/ (?{ local $s_pos = pos; }) [A-Z] (?{ print("[", substr($_, $s_pos, pos()-$s_pos), "]\n") }) /x; $re0 = qr/ (??{ $re1 }) (??{ $re1 }) /x; 'abcDE' =~ $re0; __END__ output ====== [D] [E]

yuck!

Update: Adding an extra capture also works! Kudos to blokhead for this solution.

use strict; use warnings; my $re0; my $re1; $re1 = qr/ ([A-Z]) (?{ print("[$1]\n") }) /x; $re0 = qr/ () (??{ $re1 }) (??{ $re1 }) /x; 'abcDE' =~ $re0; __END__ output ====== [D] [E]

Replies are listed 'Best First'.
Re^2: Using a capture in /(?{...})/
by ikegami (Patriarch) on Jul 25, 2005 at 21:58 UTC

    I spoke too soon, kinda.

    pos works, but gives a weird warning when + is used:

    use strict; use warnings; my $re0; my $re1; our $s_pos; $re1 = qr/ (?{ local $s_pos = pos; }) [A-Z] (?{ print("[", substr($_, $s_pos, pos()-$s_pos), "]\n") }) /x; $re0 = qr/ (?: (??{ $re1 }) )+ /x; 'abcDE' =~ $re0; __END__ output ====== (?: (??{ $re1 }) )+ matches null string many times before HERE mark in regex m/ (?: (??{ $re1 }) )+ << HERE / at script.pl line 19. [D] [E]

    Same with the extra capture:

    use strict; use warnings; my $re0; my $re1; $re1 = qr/ ([A-Z]) (?{ print("[$1]\n") }) /x; $re0 = qr/ (?: () (??{ $re1 }) )+ /x; 'abcDE' =~ $re0; __END__ (?: () (??{ $re1 }) )+ matches null string many times before HERE mark in regex m/ (?: () (??{ $re1 }) )+ << HERE / at script.pl line 17. [D] [E]

    However, the warning seems to be spurious. The warning check is using a variable that's not updated, but the pos truly is changing.

      The warning comes from the fact that Perl can't tell if (?{ ... }) matches any characters or not, so it's possible you're putting a quantifier on a zero-width assertion.

      Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
      How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart

        You mean (??{ ... }). ((?{ ... }) is always zero-width.) Ok, the warning makes sense. There are (at least) two ways of hidding it:

        1) Use no warnings 'regexp', or

        2) refactor the regexp to hide that particular instance of the warning while leaving others on. For example,

        $re0 = qr/ (??{ $re1 })* /x;

        can be written as:

        $re0 = qr/ (??{ $re1 }) (??{ $re0 }) | # Nothing /x;

        and

        $re0 = qr/ (??{ $re1 })+ /x;

        can be written as:

        $re0 = qr/ (??{ $re1 }) (??{ $re0_ }) /x; $re0_ = qr/ (??{ $re1 }) (??{ $re0_ }) | # Nothing /x;

        and

        $re0 = qr/ (??{ $re1 })? /x;

        can be written as:

        $re0 = qr/ (??{ $re1 }) | # Nothing /x;