什么是正确的 Raku 递归正则表达式语法?

8
Raku递归正则表达式语法和所有匹配变量是什么,以及它们在尝试中的作用。
'hellohelloworldworld' ~~ m{ ^(h\w+?o) (?0) world  };
say "\n=$&"

似乎不起作用。

请帮助解决这些问题。


@raiph 这个问题应该有一个关于“匹配变量发布”的答案。请考虑重新发布,谢谢。 - jubilatious1
@raiph 是的,但您引用的是3.5年前最初发布的问题的答案。我个人希望编译器自那时以来已经发展,因此当时可能被认为是错误的东西已经被纳入文档,或者已经被排除了。也就是说...从现在开始,关于Rakudo的“匹配变量的发布”方面的2022年更新答案将是最有价值的。问候。 - jubilatious1
@raiph,仍然希望确认/否认是否仍需要“发布”匹配变量。如先前所述,我使用 say $/ if 'hellohelloworldoworld' ~~ m/ ^(h\w+?o) {$0} world /; 可以得到期望的答案。我正在运行 REPL 版本 moar (2021.06) - jubilatious1
啊啊啊。我一直在使用错误的输入字符串(...worldoworld)。现在我明白了:say $/ if 'hellohelloworldworld' ~~ m/ ^(h\w+?o) {} $0 world /; 可以正常工作。我的测试表明,“发布”确实仍然是必需的。 - jubilatious1
2
@jubilatious 我认为这是问题被更改了,所以不是你的错 :-) - Sebastian
2个回答

8
Raku有专门用于匿名递归正则表达式的语法:<~~>
使用这种语法,您可以将问题中的正则表达式编写为:
'hellohelloworldworld' ~~ m{ ^(h\w+?o) <~~>? world  };

say $/; # OUTPUT: «「hellohelloworld」␤
        #          0 => 「hellohello」␤»

3
“老师,我真的没有抄袭!” :) (我几个小时前已经修改了我的回答,包括自递归的内容和一个虚假但可能有趣的“答案3”。但是由于风暴科里的原因,我的网络连接不稳定,然后被拦住了,所以没能及时发布。) - raiph
有些困惑,因为没有 <~~> 这个符号,代码 say $/ if 'hellohelloworldworld' ~~ m{ ^(h\w+?o) world }; 仍然返回相同的结果。我使用的 REPL 版本是 moar (2021.06) - jubilatious1

3

我预期看到的两个答案已经发布了,它们是:

  1. 在同一正则表达式/匹配操作中,将一个匹配变量用作以后使用的"{} 出版物" (技术上称为反向引用):
    > say $/ if 'hellohelloworldworld' ~~ m/ ^(h\w+?o) {} $0 world /;
    「hellohelloworld」
     0 => 「hello」
    > say $/ if 'hellohelloworldworld' ~~ m/ ^(h\w+?o) world /;
    「hellohelloworld」
     0 => 「hellohello」

其次,可以在正则表达式内使用Raku专用的“<~~>递归匹配”运算符。

然而,在真正的TMTOWTDI精神中,还有第三种选择,使用Raku的:nd()限定词来实现一种“穷人版”递归。从['(' \w* ]分组开始,您可以依次从输入字符串(bird(in(nest)))中提取「(bird」「(in」「(nest」。或者一次性全部提取(最后一个示例):

在Raku REPL中:

> my $nested = "(bird(in(nest)))";
(bird(in(nest)))
> say $nested;
(bird(in(nest)))
> say  $nested ~~ m:1st/ ['(' \w* ] /;
「(bird」
> say  $nested ~~ m:2nd/ ['(' \w* ] /;
「(in」
> say  $nested ~~ m:3rd/ ['(' \w* ] /;
「(nest」
> say  $nested ~~ m:nd(1..3)/ ['(' \w* ] /;
(「(bird」 「(in」 「(nest」)
>

在幕后,这很可能使用了Raku的:position副词或:continue副词,并结合Raku的$/.to匹配变量。
> say  $nested ~~ m/ ['(' \w* ] /;
「(bird」
> say  $nested ~~ m:pos($/.to)/ ['(' \w* ] / given $nested ~~ m/ ['(' \w* ] /;
「(in」
> say  $nested ~~ m:pos($/.to)/ ['(' \w* ] / given $nested ~~ (m/ ['(' \w* ] / && m:pos($/.to)/ ['(' \w* ] /);
「(nest」
> 

再次强调,Raku语言为解决问题提供了许多不同的方式,这是该语言的一个优点。


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