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

后端 未结 5 976
无人及你
无人及你 2020-12-15 06:01

I have a regex:

/abc(def)ghi(jkl)mno(pqr)/igs

How would I capture the results of each parentheses into 3 different variables, one for each

5条回答
  •  攒了一身酷
    2020-12-15 07:00

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

    #!/usr/bin/perl
    
    use strict; use warnings;
    
    my %data;
    
    my $s = 'abcdefghijklmnopqr';
    
    if ($s =~ /abc (?def) ghi (?jkl) mno (?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/perl
    
    use 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;
    }
    

提交回复
热议问题