How can I store captures from a Perl regular expression into separate variables? How can I store captures from a Perl regular expression into separate variables? arrays arrays

How can I store captures from a Perl regular expression into separate variables?


Your question is a bit ambiguous to me, but I think you want to do something like this:

my (@first, @second, @third);while( my ($first, $second, $third) = $string =~ /abc(def)ghi(jkl)mno(pqr)/igs) {    push @first, $first;    push @second, $second;    push @third, $third;}


Starting with 5.10, you can use named capture buffers as well:

#!/usr/bin/perluse strict; use warnings;my %data;my $s = 'abcdefghijklmnopqr';if ($s =~ /abc (?<first>def) ghi (?<second>jkl) mno (?<third>pqr)/x ) {    push @{ $data{$_} }, $+{$_} for keys %+;}use Data::Dumper;print Dumper \%data;

Output:

$VAR1 = {          'first' => [                       'def'                     ],          'second' => [                        'jkl'                      ],          'third' => [                       'pqr'                     ]        };

For earlier versions, you can use the following which avoids having to add a line for each captured buffer:

#!/usr/bin/perluse strict; use warnings;my $s = 'abcdefghijklmnopqr';my @arrays = \ my(@first, @second, @third);if (my @captured = $s =~ /abc (def) ghi (jkl) mno (pqr) /x ) {    push @{ $arrays[$_] }, $captured[$_] for 0 .. $#arrays;}use Data::Dumper;print Dumper @arrays;

Output:

$VAR1 = [          'def'        ];$VAR2 = [          'jkl'        ];$VAR3 = [          'pqr'        ];

But I like keeping related data in a single data structure, so it is best to go back to using a hash. This does require an auxiliary array, however:

my %data;my @keys = qw( first second third );if (my @captured = $s =~ /abc (def) ghi (jkl) mno (pqr) /x ) {    push @{ $data{$keys[$_]} }, $captured[$_] for 0 .. $#keys;}

Or, if the names of the variables really are first, second etc, or if the names of the buffers don't matter but only order does, you can use:

my @data;if ( my @captured = $s =~ /abc (def) ghi (jkl) mno (pqr) /x ) {    push @{ $data[$_] }, $captured[$_] for 0 .. $#captured;}


An alternate way of doing it would look like ghostdog74's answer, but using an array that stores hash references:

my @results;while( $string =~ /abc(def)ghi(jkl)mno(pqr)/igs) {    my ($key1, $key2, $key3) = ($1, $2, $3);    push @results, {         key1 => $key1,        key2 => $key2,        key3 => $key3,    };}# do something with itforeach my $result (@results) {    print "$result->{key1}, $result->{key2}, $result->{key3}\n";}

with the main advantage here of using a single data structure, AND having a nice readable loop.