当我运行此代码时:
$_='xaxbxc';
if(/(x(?<foo>.))+/) {
say "&: ", $&;
say "0: ", $-{foo}[0];
say "1: ", $-{foo}[1];
}
我明白了:
&: xaxbxc
0: c
1:
我理解这是它应该如何工作,但我希望能够以某种方式获得所有匹配('a', 'b', 'c')
的列表,而不仅仅是最后一个匹配(c
)。我怎么能这样做?
答案 0 :(得分:4)
我认为通常没有办法做到这一点(如果我错了请纠正我),但在特定情况下可能有办法实现相同的最终目标。例如,这适用于您的特定代码示例:
$_='xaxbxc';
while (/x(?<foo>.)/g) {
say "foo: ", $+{foo};
}
你到底想要完成什么?也许我们可以为您的实际问题找到解决方案,即使没有办法重复捕获。
答案 1 :(得分:3)
Perl允许正则表达式多次匹配“g”开关超过结尾。然后可以循环每个单独的匹配,如Using Regular Expressions in Perl section of the Perl Regex Tutorial的全局匹配子部分所述:
while(/(x(?<foo>.))+/g){
say "&: ", $&;
say "foo: ", $+{foo};
}
这将生成一个迭代列表:
&: xa
foo: a
&: xb
foo: b
&: xc
foo: c
哪个仍然不是你想要的,但它真的很接近。将全局正则表达式(/ g)与之前的本地正则表达式相结合可能会做到这一点。通常,在重复的组周围创建一个捕获组,然后使用仅表示该组的单个迭代的全局正则表重新解析该组,并迭代它或将其用作列表。
这看起来像一个与这个问题非常相似的问题 - 至少在答案中,如果不是在论坛中 - 已经被Perl比我更有能力的人回答:"Is there a Perl equivalent of Python's re.findall/re.finditer (iterative regex results)?"你可能想要检查答案关于正确使用全局正则表达式的更多细节。 (Perl不是我的语言,我对正则表达式不满意。)
答案 2 :(得分:3)
在这种情况下,使用嵌入式代码块提供了一种简单的方法:
my @match;
$_='xaxbxc';
if(/((?:x(.)(?{push @match, $^N}))+)/) {
say "\$1: ", $1;
say "@match"
}
打印:
$1: xaxbxc
a b c
答案 3 :(得分:1)
当您在同一模式中具有多个相同的命名组时,使用%-
变量,而不是在给定组碰巧迭代时。
这就是为什么/(.)+/
没有加载$1
每个单独的字符,只是最后一个字符。与/(<x>.)+/
相同。但是,对于/(<x>.)(<x>.)/
,您有两个不同的<x>
组,因此$-{x}
。考虑:
% perl -le '"foobar" =~ /(?<x>.)(?<x>.)/; print "x#1 is $-{x}[0], x#2 is $-{x}[1]"'
x#1 is f, x#2 is o
% perl -le '"foobar" =~ /(?:(?<x>.)(?<x>.))+/; print "x#1 is $-{x}[0], x#2 is $-{x}[1]"'
x#1 is a, x#2 is r
答案 4 :(得分:0)
我不确定这正是您正在寻找的,但以下代码应该可以解决问题。
$_='xaxbxc';
@l = /x(?<foo>.)/g;
print join(", ", @l)."\n";
但是,我不确定这会对重叠的字符串起作用。