Raku 正则表达式:如何知道哪个组被交替捕获

Jul*_*lio 10 regex rakudo regex-group regex-alternation raku

使用 perl(以及几乎所有正则表达式),每个组都按顺序编号。

例如,这段代码:

'bar' =~ m/(foo)|(bar)/;

print $1 // 'x'; # (1-based index)
print $2 // 'x'; # (1-based index)
Run Code Online (Sandbox Code Playgroud)

印刷 xbar

但是,对于 Raku,它的行为就像有一个分支重置组包裹了整个正则表达式:

'bar' ~~ m/(foo)|(bar)/;

print $0 // 'x'; # (0-based index)
print $1 // 'x'; # (0-based index)
Run Code Online (Sandbox Code Playgroud)

印刷 barx

我对这种行为没意见:)。然而,有时知道哪个组在交替下被捕获是有用的。

怎么知道有raku的组?

use*_*601 10

有几种方法可以做到,具有不同程度的效用。

一种方法是明确告诉 Raku 你想要的数字是什么:

'bar' ~~ m/$1=(foo)|$2=(bar)/;
Run Code Online (Sandbox Code Playgroud)

如果您扩展正则表达式,计数将继续以 3 美元计算。

一个不太推荐的方法是偷偷加入一组额外的括号:

'bar' ~~ m/(foo)|()(bar)/;
Run Code Online (Sandbox Code Playgroud)

foo将匹配 $0 中的第一个并且 $1 将是未定义的,并且bar将匹配 $1 并且 $0 为空(但不是未定义)。TIMTOWTDI 但这不是一个好方法 ;-)

另一种方法是使用标志:

 my $flag;
'bar' ~~ m/(foo {$flag = 'first'} ) | (bar {$flag = 'second'} )/;
Run Code Online (Sandbox Code Playgroud)

标志将根据比赛设置。这实际上是一种并不可怕的做事方式,特别是如果您的标志是二进制的并且您将有一些逻辑可以运行它。

另一种类似的方法是利用通常在动作类中使用的.make/ .made,但仍然可以内联使用:

'bar' ~~ m/(foo {make 'first'} ) | (bar {make 'second'} )/;
say $0.made; # 'second'
Run Code Online (Sandbox Code Playgroud)

如果您有很多想要与之关联的元数据(但仅仅知道选择了哪个可能有点过分),那么这个就很好了。