Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 在perl中将分组元素存储在两个不同的数组中?_Regex_Perl - Fatal编程技术网

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

Regex 在perl中将分组元素存储在两个不同的数组中?,regex,perl,Regex,Perl,我试图将第一组存储在@a1中,将第二组存储在@a2 my $string = "abc123def456abc321def654"; my (@a1,@a2) = $string =~m/abc(\d+)def(\d+)/g; $, = "\n"; print @a1; 结果是123456321654,然后@a2为空。但我希望结果是@a1=123321@a2=456654 对于这个结果,我尝试了散列,用于存储的键是第一个分组,值是第二个分组,但问题是删除了重复项。有没有任何可能的方法可以通过

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

my $string = "abc123def456abc321def654";
my (@a1,@a2) = $string =~m/abc(\d+)def(\d+)/g;
$, = "\n";
print @a1; 
结果是
123456321654
,然后
@a2
为空。但我希望结果是
@a1=123321
<代码>@a2=456654 对于这个结果,我尝试了散列,用于存储的键是第一个分组,值是第二个分组,但问题是删除了重复项。有没有任何可能的方法可以通过一个正则表达式匹配来实现呢

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

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

1234
321
666
4567
456
45
4
654
65
6
777
77
7
@a2
结果为

1234
321
666
4567
456
45
4
654
65
6
777
77
7

这就是你想要的

#!/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”),然后再进行分配。

您可以:

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


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

更新添加了一个版本,根据需求澄清,该版本在正则表达式中完成所有操作。


构建哈希:键是模式(
abc
def
,等等),值是数组引用及其匹配项

 my %h;
() = $string =~ /([a-z]+)(\d+)(?{push @{$h{$1}}, $2;})/g;
需要使用
()
来强制列表上下文,否则只会发生第一个匹配,而
/g
只会使它从一个匹配跳到另一个匹配。看见请注意,在匹配部件中运行代码是一个实验特性。相反,您可以对替换部分中的代码求值

my %h;
$string =~ s/([a-z]+)(\d+)/{push @{$h{$1}}, $2}/eg;
这当然会破坏原始字符串

结果散列包含的键是模式(
abc
def
,…),键值为数组ref,该键的所有匹配项均为数组ref。您可以有任意数量的模式数字对,而不仅仅是两个。见下文

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


最初发布

这假定一个模式(您的
abc
def
)后跟数字。根据您的示例,这里使用的模式是
[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 def => 456 654 abc => 123 321 ghi => 111 222 印刷品

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

我找到了问题的答案。我使用原子组并捕获结果。回溯是我第二个案例的问题,所以我使用了原子组,帮助避免回溯

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

我认为这个答案可能会受益于解释为什么数字都会出现在第一个数组中;用
说join(“,”,@a1)说@a2
;说join(“,”,@a2)您将看到所有的数字都不在第一个数组中。@Marty我用
\G
尝试了eval group,有什么方法可以这样做吗。@Sobrique有什么方法可以用eval group来做吗?除了说\d+第一次用$2给您456,然后正则表达式将再次尝试并成功,用$2表示45,然后用4再次成功-因为它们都满足\d+-但是当它们不在原始字符串中时,如何在其中获得'7',我不知道。锚的使用会阻止重复匹配。你为什么要强迫它成为一个单一的正则表达式?@sorbrique我有一个采访电话,他说这是可能的,只有一个正则表达式。所以我在一个评估小组里试了很长时间,但我还是没能得到result@mkHun因为你似乎在正则表达式中严格地需要它,所以我把它添加到了我的答案中。谢谢你的帮助。我从你那里学到了新东西。但我用原子团找到了我问题的答案。:)我不知道-1是干什么用的。代码运行并打印,如图所示。