我最近在regexp中发现了命名捕获组的强大功能。不幸的是,似乎我不能以不同的顺序使用它们。
让我们考虑这个短价格表:
15 USD
CHF 18
我想检索货币及其价值。所以,我天真地写了这个:
(?|
(?<value>\d+)\s*(?<currency>[a-z]+)
|
(?<currency>[a-z]+)\s*(?<value>\d+)
)
不幸的是,在这里可见(https://regex101.com/r/uE8qE1/1),正则表达式有错误。但是,我在Perl中没有收到任何错误,我可以访问$+{currency}
和$+{value}
,但我有时会将货币输入值,反之亦然。
有没有办法在叮咬中捕捉混合元素?
修改
以下是Perl中显示问题的示例:
#!/usr/bin/env perl
use 5.014;
my $_ = "14 USD
CHF 15";
while(/(?|
(?<value>[0-9]+)\s*(?<currency>[a-z]+)
|
(?<currency>[a-z]+)\s*(?<value>[0-9]+)
)/igmx) {
say "Currency: $+{currency}\tValue: $+{value}";
}
输出:
$ ./test.pl
Currency: USD Value: 14
Currency: 15 Value: CHF
答案 0 :(得分:1)
看起来分支重置模式会混淆正则表达式引擎。
use strict;
use warnings;
use 5.010;
while (<DATA>) {
next unless /(?<value>\d+)\s*(?<currency>[a-z]+) | (?<currency>[a-z]+)\s*(?<value>\d+)/ix;
say "$+{value} $+{currency}";
}
__DATA__
15 USD
CHF 18
<强>输出强>
15 USD
18 CHF
<强>更新强>
@PatrickJ.S.
非常有帮助,指出在&#34;扩展模式&#34; 下的perlre
中记录了这种情况。 分支重置部分说明了这一点。粗体是我自己的。
将分支重置模式与命名捕获结合使用时要小心。命名捕获被实现为包含捕获的编号组的别名,并且干扰分支重置模式的实现。 如果您在分支重置模式中使用命名捕获,则最好在每个替换中以相同的顺序使用相同的名称
据我所知,当有多个具有相同名称的命名捕获时,没有提及任何行为,所以即使你按照预期的那样工作,你也处于非常不稳定的状态。
答案 1 :(得分:1)
对于任何试图使用以任何顺序匹配的捕获组(特别是命名的捕获组)的人,我的建议是提前进行捕获:
use 5.014;
$_ = "
CHF 15
14 USD
";
while(/(?=.*?\b(?<value>[0-9]+)\b)(?=.*?\b(?<currency>[a-z]+)\b)/igmx) {
say "Currency: $+{currency}\tValue: $+{value}";
}
产生
Currency: CHF Value: 15
Currency: USD Value: 14