我有一个正则表达式:
/abc(def)ghi(jkl)mno(pqr)/igs
我如何将每个括号的结果捕获到 3 个不同的变量中,每个括号一个?现在我使用一个数组来捕获所有结果,它们是按顺序出现的,但是我必须解析它们并且列表可能很大。
@results = ($string =~ /abc(def)ghi(jkl)mno(pqr)/igs);
我有一个正则表达式:
/abc(def)ghi(jkl)mno(pqr)/igs
我如何将每个括号的结果捕获到 3 个不同的变量中,每个括号一个?现在我使用一个数组来捕获所有结果,它们是按顺序出现的,但是我必须解析它们并且列表可能很大。
@results = ($string =~ /abc(def)ghi(jkl)mno(pqr)/igs);
你的问题对我来说有点模棱两可,但我认为你想做这样的事情:
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;
}
从 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;
输出:
$VAR1 = { '第一' => [ '定义' ], '第二' => [ 'jkl' ], '第三' => [ '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 = [ '定义' ]; $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;
}
或者,如果变量的名称确实是first
,second
等等,或者如果缓冲区的名称无关紧要但只有顺序,您可以使用:
my @data;
if ( my @captured = $s =~ /abc (def) ghi (jkl) mno (pqr) /x ) {
push @{ $data[$_] }, $captured[$_] for 0 .. $#captured;
}
另一种方法看起来像 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";
}
这里的主要优点是使用单个数据结构,并且具有良好的可读循环。
@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
您可以拥有三个不同的正则表达式,每个都专注于特定的组。显然,您只想将不同的组分配给正则表达式中的不同数组,但我认为您唯一的选择是将正则表达式拆分。
您可以编写一个包含命名捕获组的正则表达式。您可以使用?<myvar>
捕获组开头的构造执行此操作:
/(?<myvar>[0-9]+)/
然后,您可以使用$+{myvar}
表单引用那些命名的捕获组。
这是一个人为的例子:
perl -ne '/^systemd-(?<myvar>[^:]+)/ && { print $+{myvar} . "\n"}' /etc/passwd
给定一个典型的密码文件,它会提取 systemd 用户并返回名称减去 systemd 前缀。它使用一个名为myvar
. 这只是一个示例,用于说明捕获组变量的使用。