in reply to Re: How to know that a regexp matched, and get its capture groups?
in thread How to know that a regexp matched, and get its capture groups?

Note that you need 5.26+ for @{^CAPTURE}.

map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

Replies are listed 'Best First'.
Re^3: How to know that a regexp matched, and get its capture groups?
by LanX (Saint) on Jan 10, 2023 at 12:10 UTC
    update

    I don't recommend the following code anymore

    rather

    if ( my (@caps) = ($line =~ $re) ) { no warnings 'uninitialized'; @caps = () if $caps[0] ne $1; # reset pseudo capture +s $cb->(@caps); last; }
    /update

    This should be backward compatible

    my (@matches) = ($line =~ $re) if (defined $&) { $cb->(@matches); last; }

    # tests...

    use v5.12; use warnings; for my $str ("AB","") { say "****** str=<$str>"; for my $re ( qr/../, qr/(.)(.)/, q/XY/, q/(X)Y/, q// ) { say "--- re=<$re>"; my @captures = $str =~ $re; if ( defined $& ) { say "matched" } else { say "no match" } if (defined $1) { say "with captures <@captures>"; } else { say "no captures"; } } }

    ****** str=<AB> --- re=<(?^u:..)> matched no captures --- re=<(?^u:(.)(.))> matched with captures <A B> --- re=<XY> no match no captures --- re=<(X)Y> no match no captures --- re=<> matched no captures ****** str=<> --- re=<(?^u:..)> no match no captures --- re=<(?^u:(.)(.))> no match no captures --- re=<XY> no match no captures --- re=<(X)Y> no match no captures --- re=<> matched no captures

    Cheers Rolf
    (addicted to the 𐍀𐌴𐍂𐌻 Programming Language :)
    Wikisyntax for the Monastery

      But...

      > See "Performance issues" above for the serious performance implications of using this variable (even once) in your code.

      perlvar

      map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
        OK, I thought this performance issue was resolved for versions newer than 10-15 years.

        Anyway

        ${^MATCH} This is similar to $& ($MATCH) except that it does not incur the perfo +rmance penalty associated with that variable. This variable was added in Perl v5.10.0.

        though I don't understand the /p comment

        Cheers Rolf
        (addicted to the 𐍀𐌴𐍂𐌻 Programming Language :)
        Wikisyntax for the Monastery

      >
      my (@matches) = ($line =~ $re) if (defined $&) { $cb->(@matches); last; }

      nope, the real problem is that @matches = (1) if it matched without capture groups in $re

      new attempt:

      if ( my (@caps) = ($line =~ $re) ) { @caps = () if $caps[0] ne $1; # reset pseudo capture +s $cb->(@caps); last; }

      Full backwards compatible and no performance penalty.

      OK?

      Cheers Rolf
      (addicted to the 𐍀𐌴𐍂𐌻 Programming Language :)
      Wikisyntax for the Monastery

        if ( my (@caps) = ($line =~ $re) ) { @caps = () if $caps[0] ne $1; # reset pseudo captures $cb->(@caps); last; }

        In
            @caps = () if $caps[0] ne $1;
        $1 will be undefined if there is no capture group 1 or it is something like (...)? that fails to match (but an overall match can still occur). Warnings will be generated.

        Although it's only compatible back to version 5.6, an alternative would be

        c:\@Work\Perl\monks>perl use strict; use warnings; use Data::Dump qw(pp); my $cb = sub { print "matched, captured ", pp @_; }; for my $str ("AB","") { for my $re (qr/../, qr/(.)(.)/, qr/(X)?(.)/, qr/XY/, qr/(X)Y/, qr/ +/) { print "str <$str> re $re "; if ( my (@caps) = ($str =~ $re) ) { # @caps = () if $caps[0] ne $1; # reset pseudo capture $#caps = $#- - 1; # reset pseudo capture $cb->(@caps); } else { print 'NO match'; } print "\n"; } } ^Z str <AB> re (?-xism:..) matched, captured () str <AB> re (?-xism:(.)(.)) matched, captured ("A", "B") str <AB> re (?-xism:(X)?(.)) matched, captured (undef, "A") str <AB> re (?-xism:XY) NO match str <AB> re (?-xism:(X)Y) NO match str <AB> re (?-xism:) matched, captured () str <> re (?-xism:..) NO match str <> re (?-xism:(.)(.)) NO match str <> re (?-xism:(X)?(.)) NO match str <> re (?-xism:XY) NO match str <> re (?-xism:(X)Y) NO match str <> re (?-xism:) matched, captured ()

        Update: But see haukex's reply about the preference for $#+ versus $#- (@+ versus @-) regex special variables.


        Give a man a fish:  <%-{-{-{-<