I wrote a code that looks like this:
my $text = <<TEXT; Title: The Moor's Last Sigh, Author: Salman Rushdie Title: The God of Small Things, Author: Arundhati Roy TEXT my @answers; my $re = qr/Title: (.*?), Author: (\w+) (\w+)$/; # 3 groups here while ($text =~ /$re/mgc) { my %ans; push @answers, [ $1, $2, $3 ]; # that's the main point! } use Data::Dump qw(dump); print dump(\@answers);
And then I got the answer I want in @answers, namely:
( ["The Moor's Last Sigh", "Salman", "Rushdie"], ["The God of Small Things", "Arundhati", "Roy"], )
Now imagine I want to run the same code against other inputs and with other regexes driving the extraction. These regexes can have an arbitrary number of capturing groups. I can't get all groups by using $text = /$re/mgc in list context, because it will make a loop over the text gathering $1, $2, ... of each match into a list (that is, $1, $2, ..., $1, $2, ..., ...). The code above is actually a simplification and it should work on a context more like this:
if ($text =~ /$re1/mgc) { ... if ($text =~ /$re2/mgc) { ... if ($text =~ /$re1/mgc) { ... if ($text =~ /$re2/mgc) { ...
So the /g behavior in list context is inappropriate. To get ($1, $2, ...) in a generic form, the only way I envisaged was to use @- and @+ and to employ a piece of code like this:
# return ($1, $2, ...) matched against $s sub _groups { my $s = shift; my @groups; foreach my $i (1..$#-) { push @groups, substr($s, $-[$i], $+[$i] - $-[$i]); } return @groups }
and then:
push @answers, [ _groups($text) ]; # [ ($1, $2, ...) ]
My question is: Is there actually a better way to do this?
In reply to How to get ($1, $2, ...)? by ferreira
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |