命名正则表达式在Raku中无法捕获

5

有人能解释一下为什么在命名正则表达式中捕获组(命名和非命名)似乎不起作用吗?我希望这是我的错误,但如果是的话,我看不出来。以下是我在 Raku REPL 中的短例子,其中包含了捕获的文本。

> my $s = '16.01.2020 09:18 286';
> my $dReg = /^(\d**2)\.(\d**2)\.(\d**4)/;
> $s ~~ /<$dReg>/;
「16.01.2020」
> if $s ~~ /<$dReg>/ { say $0 }
Nil
> my $dReg1 = /^$<day> = (\d**2)\.$<mon> = (\d**2)\.$<year> = (\d**4)/;
/^$<day> = (\d**2)\.$<mon> = (\d**2)\.$<year> = (\d**4)/
> $s ~~ /<$dReg1>/;
「16.01.2020」
> if $s ~~ /<$dReg1>/ { say $<day> }
Nil
> if $s ~~ /^$<day> = (\d**2)\.$<mon> = (\d**2)\.$<year> = (\d**4)/ { say $<day> }
「16」
> if $s ~~ /^(\d**2)\.(\d**2)\.(\d**4)/ { say $0 }
「16」
2个回答

8
问题出现在正则表达式的使用处 - 即<$dReg>。任何以非标识符开头的断言语法都不会被捕获。解决方法是为其引入一个名称,以便在其下被捕获。例如,这样做:
my $s = '16.01.2020 09:18 286';
my $dReg = /^(\d**2)\.(\d**2)\.(\d**4)/;
say $s ~~ /<dreg=$dReg>/;

结果为:

「16.01.2020」
 dreg => 「16.01.20200 => 「161 => 「012 => 「2020

你可以通过$<dreg>[0]访问捕获结果。这是因为在Raku正则表达式中,每个规则调用级别都暗示了一个嵌套级别。这也使得它们能够扩展到完整的语法。

请注意,如果您只想匹配包含正则表达式的变量,则完全可以(并且更有效率)。在这种情况下,您将直接获得捕获结果。例如:

my $s = '16.01.2020 09:18 286';
my $dReg = /^(\d**2)\.(\d**2)\.(\d**4)/;
say $s ~~ $dReg;

生成:

「16.01.2020」
 0 => 「161 => 「012 => 「2020

我喜欢裸for循环,简洁明了,而且更高效! - hsmyers

4

参见jnthn的回答。

另一个选项是声明一个命名正则表达式(这不同于一个具有名称并包含正则表达式的变量)。例如:

my $input = 'foo';
my regex dreg { 'foo' }
if $input ~~ /<dreg>/ { say $<dreg> } # 「foo」

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接