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

Hello Monks,

I've recently learned about the DEFINE predicate and I'm testing it with a simple script that I wrote to practice Perl and regular expressions. The script simply checks for IPv4 or IPv6 addresses (I know there is a CPAN module for that, this is for me to practice), and I re-wrote the regular expression like so:

my $re = qr{ (?> \b ((?&IPV6) | (?&IPV4)) \b ) (?(DEFINE) (?<IPV6> ( ((?&H16) :){6} (?&LS32)) | ( :: ((?&H16) :){5} (?&LS32)) | (( (?&H16))? :: ((?&H16) :){4} (?&LS32)) | ((((?&H16) :){0,1} (?&H16))? :: ((?&H16) :){3} (?&LS32)) | ((((?&H16) :){0,2} (?&H16))? :: ((?&H16) :){2} (?&LS32)) | ((((?&H16) :){0,3} (?&H16))? :: ((?&H16) :){1} (?&LS32)) | ((((?&H16) :){0,4} (?&H16))? :: (?&LS32)) | ((((?&H16) :){0,5} (?&H16))? :: (?&H16) ) | ((((?&H16) :){0,6} (?&H16))? :: ) ) (?<LS32> ((?&H16) : (?&H16)) | (?&IPV4) ) (?<H16> (?&HEX_DIGIT){1,4} ) (?<HEX_DIGIT> [a-fA-F0-9] ) (?<IPV4> ((?&DEC_OCTET)\.){3}(?&DEC_OCTET) ) (?<DEC_OCTET> 25[0-5]|2[0-4]\d|1\d\d|\d\d|\d ) (?<IP_VFUTURE> v(?&HEX_DIGIT)+\.((?&UNRESERVED) | (?&SUB_DELIMS) | : )+ ) (?<UNRESERVED>[a-zA-Z0-9\-\._~] ) (?<SUB_DELIMS>[!\$&'\(\)\*\+,;=] ) ) }x;

It works, but it only seems to capture the first occurrence of an IP address on each line. For example:

if ("This is the same address in IPv6: 0:0:0:0:0:0:0:1 and 127.0.0.1" +=~ /$re/g ) { say $&; say $1; say $2; }

I was expecting to capture both IP addresses, but only the first is ever captured. Can anyone shed some light on how could I make this work in this way?

Thank you!

Replies are listed 'Best First'.
Re: regex capture groups when using DEFINE predicate
by Corion (Patriarch) on Apr 03, 2025 at 10:45 UTC

    A single match (re)sets $1 and $2 (and so on).

    If you want to match a regular expression multiple times, you need to do something like:

    my @matches = /$re/g;

    or

    while( $line =~ /$re/g ) { say $1 // $2; }

      Oh, that's right I forgot about that!

      Thank you, everything is working fine now with this adjustment. Cheers.