在perl中将分组元素存储在两个不同的数组中?

时间:2016-04-04 05:31:07

标签: regex perl

我尝试将第一组存储在@a1中,将第二组存储在@a2

my $string = "abc123def456abc321def654";
my (@a1,@a2) = $string =~m/abc(\d+)def(\d+)/g;
$, = "\n";
print @a1; 

结果为123 456 321 654,然后@a2为空。但我希望结果是@a1 = 123 321; @a2 = 456 654 对于这个结果我尝试哈希,为了存储键是第一次分组,值是第二次分组但问题是重复删除。使用单个正则表达式匹配的任何可能的方法吗?

我在模式匹配中尝试了eval group。我从@a1得到了正确的结果,但@a2出错了。而且不知道是什么问题?

my (@a1, @a2);
$string =~m/abc(\d+) (?{push @a1, $1}) def(\d+)(?{push @a2,$2 }) \G/x;

@a1结果是

1234
321
666

@a2结果是

4567
456
45
4
654
65
6
777
77
7

4 个答案:

答案 0 :(得分:2)

你可以这样做:

use List::Util 'pairs';
my @a12 = pairs $string =~ /abc(\d+)def(\d+)/g;
my @a1 = map $_->[0], @a12;
my @a2 = map $_->[1], @a12;

use List::MoreUtils 'part';
my $i = 0;
my @part = part { $i++ % 2 } $string =~ /abc(\d+)def(\d+)/g;
my @a1 = @{ $part[0] };
my @a2 = @{ $part[1] };

或者只是跳过设置@ a1和@ a2并使用@ a12或@part中的数据。

答案 1 :(得分:1)

这就是你所追求的;

#!/usr/bin/env perl
use v5.12;

my $string = "abc123def456abc321def654";
my (@a1, @a2);
while ($string =~ /abc(\d+)def(\d+)/g) {
    push @a1, $1;
    push @a2, $2;
}
$, = "\n" ;
say @a1;
say @a2;

# Output
# 123
# 321
# 456
# 654

作为一般规则,尽量不要假设比赛成功。而不是直接赋值给变量,首先对匹配结果执行布尔测试('if'或'while),然后进行赋值。

答案 2 :(得分:1)

更新根据需求说明添加了一个在regex中完成所有操作的版本。

构建哈希:Key是模式(abcdef等),value是带有匹配项的数组引用。

 my %h;
() = $string =~ /([a-z]+)(\d+)(?{push @{$h{$1}}, $2;})/g;

需要()来强加列表上下文,因为否则只会发生第一次匹配,而/g只会使其从匹配跳转到匹配。见perlrequick。请注意,在匹配部分中运行代码是一项实验性功能。相反,您可以在替换部分中评估代码。

my %h;
$string =~ s/([a-z]+)(\d+)/{push @{$h{$1}}, $2}/eg;

这当然对原始字符串具有破坏性。

生成的散列具有作为模式(abcdef,...)的键,键值为array-ref,并且该键具有所有匹配项。您可以拥有任意数量的模式 - 数字对,而不仅仅是两个。见下文。

这两种变体的打印方式如下所示。

最初发布

这假设一种模式(您的abcdef)后跟数字。根据您的示例,此处使用的模式为[a-zA-Z]。你可以拥有任意数量的这样的对,而不仅仅是两对。

use warnings;
use strict;

my $string = "abc123def456abc321def654";

my %h; 
my $patt = qr/[a-zA-Z]/;  # for example

push @{$h{$1}}, $2  while ($string =~ /($patt+)(\d+)/g);

print "$_ => @{$h{$_}}\n" for keys %h;

打印

def => 456 654 
abc => 123 321 

有两个以上的模式数字对(已添加ghi111ghi222),

my $string = "abc123def456abc321ghi111def654ghi222";
# exactly the same code ...

打印

def => 456 654 
abc => 123 321 
ghi => 111 222

答案 3 :(得分:1)

我找到了问题的答案。我使用原子组并捕获结果。回溯是我的第二种情况的问题所以我使用原子组,有助于避免回溯。

$string =~m/abc(\d+)(?{push @a1, $1;})def(?>(\d+)) (?{ push @a2,$2; })\G/x;