为什么这个带有预定义正则表达式的后置断言没有按预期工作?

编程语言 2026-07-11

为什么第三次和第四次替换会产生不同的结果?

#!/usr/bin/env raku
use v6.d;

my $str;

my regex myregex1 { <[\d;]>+ };

$str = "abc3def0ghi";
$str.=subst( / <?after <[\d;]>+> /, '***', :g );
say $str;   # abc3***def0***ghi

$str = "abc3def0ghi";
$str.=subst( / <?after <myregex1>> /, '***', :g );
say $str; # abc3***def0***ghi


my regex myregex2 { \e\[<[\d;]>*m };

$str = "abc\e[33mdef\e[0mghi";
$str.=subst( / <?after \e\[<[\d;]>*m> /, '***', :g );
say $str; # abc***def***ghi

$str = "abc\e[33mdef\e[0mghi";
$str.=subst( / <?after <myregex2>> /, '***', :g );
say $str; # abcdefghi

解决方案

TL;DR 这其实是个错误(正如你可能已经怀疑/猜到的那样)。

我已经把它做得足够短,这时候就该发帖了。

$_ = 'aba';

say .pos given m/ <?after    ab>    /; # 2
say .pos given m/ <?after <{'ab'}>> /; # 3

我对Rakudo的问题进行了检索(针对 regex after),并立即发现了若干在初看之下看起来非常相关的错误。

你这个问题所演示的错误,以及我对它的简化,可能与在 after 断言中使用子正则表达式有关。

不过,基于对相关错误只看了几秒钟的直觉,我觉得存在一个更普遍的潜在问题,涉及在多种形式的断言中使用子正则表达式,或许很多种。

再说,如果它真的如此简单且普遍,我们至今还没发现并搞清楚它,实在令人难以置信。

所以也许我的第一直觉是错的。

我认为你和我中的任一人都应该提交一个新的bug(除非我们找到另一个已经足够覆盖这个 after 情况的bug),并在一个或多个现有的bug上添加注释,以尽量把现有错误之间的联系理清楚。

不管怎样,先把这条发上来吧。

PS.谢谢。首先感谢你提交了一个相对比较精简的起点。其次,因为我 💖 给Condors打分!

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章