如何将Perl正则表达式中的捕获存储到单独的变量中?

时间:2010-02-14 01:12:21

标签: arrays regex perl regex-group

我有正则表达式:

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

我如何将每个括号的结果捕获到3个不同的变量中,每个变量一个?现在我使用一个数组来捕获所有结果,它们是连续的,但后来我必须解析它们,列表可能很大。

@results = ($string =~ /abc(def)ghi(jkl)mno(pqr)/igs);

5 个答案:

答案 0 :(得分:16)

你的问题对我来说有点模棱两可,但我想你想做这样的事情:

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;
}

答案 1 :(得分:6)

从5.10开始,您也可以使用named capture buffers

#!/usr/bin/perl

use 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;

输出:

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

对于早期版本,您可以使用以下内容,以避免必须为每个捕获的缓冲区添加一行:

#!/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;

输出:

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

但我喜欢将相关数据保存在单个数据结构中,因此最好回到使用哈希。但这需要一个辅助数组:

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;
}

或者,如果变量的名称确实是firstsecond等,或者如果缓冲区的名称无关紧要但只有顺序,则可以使用:

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

答案 2 :(得分:3)

另一种方法是看看ghostdog74的答案,但是使用一个存储哈希引用的数组:

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 it

foreach my $result (@results) {
    print "$result->{key1}, $result->{key2}, $result->{key3}\n";
}

这里的主要优点是使用单一数据结构,并且具有良好的可读循环。

答案 3 :(得分:2)

@OP,当捕获括号时,你可以使用变量$ 1,$ 2 ....这些是后向引用

$string="zzzabcdefghijklmnopqrsssszzzabcdefghijklmnopqrssss";
while ($string =~ /abc(def)ghi(jkl)mno(pqr)/isg) {
    print "$1 $2 $3\n";
}

输出

$ perl perl.pl
def jkl pqr
def jkl pqr

答案 4 :(得分:0)

你可以有三种不同的正则表达式,每种都集中在特定的组上。显然,你想在正则表达式中将不同的组分配给不同的数组,但我认为你唯一的选择是将正则表达式分开。