Is there an easy way to get a list of all successful captures from the pre-5.10 regex?

I know the right way to do this if I have Perl 5.10 to use named captures and values %+ , but in Perl 5.8.9 and how can I get a list of successful captures? I came up with two methods that are just terrible:

 #you need to list each possible match my @captures = grep { defined } ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16); 

and

 #ew, I turned on symbolic references { no strict 'refs'; my @captures = map { defined $+[$_] ? $$_ : () } 1 .. $#+; } 

There is a third option that I found involving (?{}) , But this requires global variables (because closure occurs at compile time) and takes a regular expression from reasonably understandable to unholy mess.

The only alternative I found is to capture the entire match and then use a different set of regular expressions to get the values ​​that I want (in fact, I create the first regular expression from other regular expressions because there is no good reason to duplicate the logic).

I obviously left an important piece of information. I use regex in a scalar context along with the \G statement, because the regex can change between matches (one of the tokens changes the way it grabs tokens from a string). For example code written for Perl 5.10, see this question , specifically this answer .

+4
source share
2 answers

You can use @+ and @- as in

 substr $var, $-[N], $+[N] - $-[N] # corresponds to $N 

But as said earlier, if you can, use the @list = grep defined, $var =~ /regex/ form.

+1
source

The following solution uses the string eval , but in a fairly safe way.

Update: I might still be missing something, but AFAICS, the fact that the pattern uses \G and matching in a scalar context matters only because the matching results cannot be assigned before @matches .

In fact, the method below is a variation of the second proposed method in the Hour. OP where he used symbolic links. IMHO, either using symbolic links or the eval string is fine, because they happen very clearly.

 #!/usr/bin/perl use strict; use warnings; my $text = <<EOT; a 2 b 3 c 3 EOT my $re = qr/([az])/; while ( $text =~ /$re/g ) { my @matches = grep defined, map eval "\$$_", 1 .. $#-; print "@matches\n"; if ( $matches[0] eq 'a' ) { $re = qr/\G\s+([0-9])\s+([az])/; next; } if ( defined $matches[1] and $matches[1] eq 'b' ) { $re = qr/\G\s+([0-9])(?: ([az]))(?: ([0-9]))/; next; } } 

Conclusion:

  C: \ Temp> jj
 a
 2 b
 3 c 3
0
source

Source: https://habr.com/ru/post/1304484/


All Articles