正则表达式中的反向引用会匹配,但不会捕获。

4

这个程序

say "zipi zape" ~~ /(\w)\w» \s+ \w+({$0})/;

返回值

「pi zape」
 0 => 「p」
 1 => 「」

我理解为"反向引用"是指第一次匹配的内容被匹配到零宽度的位置?也许是因为它被匹配到$0,这个值在正则表达式外面表示为空字符串''? 我应该如何使用这些反向引用,并同时捕获匹配内容? : 这与此文档问题有关,需要澄清反向引用的用法。

2
在撰写本文时,您在原始问题和您对Håkon答案的评论中提出的所有问题和问题都在我的回答“为什么/如何在匹配重复任意字符时需要额外的变量与捕获组?”中仔细解释。您认为值得走过您版本的问题和问题吗?如果您阅读了我的链接答案并认为您的答案不同,我将很乐意写一个答案,但现在我认为它基本上是重复的。 - raiph
2个回答

4
根据文档的说明:

如果需要从另一个捕获中引用一个捕获,请先将其存储在变量中。

因此,您可以使用以下内容:
say "zipi zape" ~~ /(\w){} :my $c = $0; \w » \s+ \w+($c)/;

输出:

「pi zap」
 0 => 「p」
 1 => 「p」

实际上,我想理解上述行为。但还有一件事情让我有点困惑,为什么你在第一个捕获后面使用开放和关闭括号? - jjmerelo
1
似乎这种使用 {} 的方式只在注释中提到:它表示我们需要用它来更新当前的匹配对象。 - Håkon Hægland
1
嗨@jjmerelo,“我想了解上述行为。”简而言之,(...)是一种简写方式,用于创建一个新的Match对象并在括号内设置$/为该新对象。因此,您的第二对括号意味着其中的$0不会指回第一对括号中的捕获。 - raiph
1
@jjmerelo,“为什么在第一个捕获后面使用开放和闭合大括号?”我已经在之前的SO中进行了解释(简要和详细),请参考我的评论作为起点。 - raiph
@raiph 感谢您提供其他问题的参考! - Håkon Hægland

3

{$0}不是反向引用。
它是一个代码块。
在这种情况下,它是一个完全没有作用的代码块。

为了将其作为正则表达式的一部分实际使用,需要在其周围加上<>


事实上,由于()表示类似于$/的新闭包,如果它被用于某些内容,它将成为空正则表达式。
(对于每个()$/都会被重置,因此$0也会被重置。)

say "zipi zape" ~~ /(\w)\w» \s+ \w+(<{$0}>)/;

Cannot resolve caller INTERPOLATE_ASSERTION(Match:D: Nil:U, BOOTInt, BOOTInt, BOOTInt, BOOTInt, PseudoStash:D); none of these signatures match:
    (Match: Associative:D, $, $, $, $, $, *%_)
    (Match: Iterable:D \var, int \im, int \monkey, int \s, $, \context, *%_)
    (Match: Mu:D \var, int \im, int \monkey, $, $, \context, *%_)
  in block <unit> at <unknown file> line 1

这是因为它基本上与(<{Nil}>)相同。


你可以通过使用{}更新第二个()之前的$/,并在$0周围使用双引号来完成。

say "zipi zape" ~~ /(\w){}\w» \s+ \w+("$0")/;
「pi zap」
 0 => 「p」
 1 => 「p」

在我看来,这似乎有点不可靠。
(它依赖于我认为是错误的特性,如果不是彻底的bug的话。)


这就是我们需要Håkon Hægland的答案来将其存储在词汇变量中的地方。
(在使用{}更新$/之后。)

say "zipi zape" ~~ /(\w){} :my $c = $0; \w » \s+ \w+($c)/;

词法变量没有限定作用域在 () 中,因此这样做是完全安全的。

个人建议将$0 转化为字符串,因为只有 $0 中的匹配对象的这一部分被使用。

say "zipi zape" ~~ /(\w){} :my $c = ~$0; \w » \s+ \w+($c)/;

说实话,我甚至没有理由去捕获第二个匹配,因为它总是与第一个匹配相同。

say "zipi zape" ~~ /(\w)\w» \s+ \w+$0/;

我认为添加 » 没有什么意义,因为 \s+ 已经强制其成为单词的结尾。

say "zipi zape" ~~ /(\w)\w \s+ \w+$0/;

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