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

Inc*_*ito 15 regex arrays perl regex-group

我有一个正则表达式:

/abc(def)ghi(jkl)mno(pqr)/igs
Run Code Online (Sandbox Code Playgroud)

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

@results = ($string =~ /abc(def)ghi(jkl)mno(pqr)/igs);
Run Code Online (Sandbox Code Playgroud)

Leo*_*ans 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;
}
Run Code Online (Sandbox Code Playgroud)

  • ghostdog74:这是一个品味问题.如果你真的将你的变量命名为$ first和$ second,那么你也可以使用$ 1和$ 2,但是如果你给它们更多的描述性名称,那么它可以提高这样做的可读性. (4认同)
  • 这有点长啰嗦.捕获时,您可以使用反向引用 (3认同)
  • -1.我不得不同意ghostdog74; 捕获到$ 1 ..系列变量在现代Perl中更加清晰.虽然你*可以*这样做,但这并不意味着它可能是最好的方法. (2认同)
  • @leon,是的,但是因为无论如何他都要把它们放在数组中,你真正关心的是数组名称.谁不知道$ 1,$ 2 ..是什么? (2认同)

Sin*_*nür 6

从5.10开始,您也可以使用命名捕获缓冲区:

#!/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;
Run Code Online (Sandbox Code Playgroud)

输出:

$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;
Run Code Online (Sandbox Code Playgroud)

输出:

$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;
}
Run Code Online (Sandbox Code Playgroud)

或者,如果变量的名字真的是first,second等,或者如果缓冲区的名字没有关系,而只是为了确实,你可以使用:

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