Raku 中 look-behind 调用预定义 regex 为何结果异常?
数据小许
结论
这段代码反映的是 Rakudo 处理 <?after ...> 中子规则调用时的问题,与 myregex2 和内联正则的匹配意图无关。在相关复现中,<?after <myregex2>> 会让匹配位置多前进一个字符。look-behind 后面紧跟 m 时,这个偏移会影响后续匹配,所以第三、第四次替换的结果不同。相关复现与分析
为什么 myregex1 看起来正常
第一组中,look-behind 后面没有要继续匹配的字符。即使子规则调用导致位置偏移,后面也没有 m 显示出差异,因此两种写法的结果相同。
第二组的内联写法是:
<?after \e\[<[\d;]>*m>
这里的 m 属于 look-behind 的匹配内容。改为调用 <myregex2> 后,look-behind 子规则匹配 \e\[<[\d;]>*m。相关复现显示,子规则形式的 after 会让匹配位置多前进一个字符。问题出在 look-behind 与子规则的交互上,和 ANSI 转义序列本身无关。
规避方式
在当前代码中,可以将 myregex2 的模式直接写在 <?after ...> 中:
my $str = "abc\e[33mdef\e[0mghi";
$str.=subst( / <?after \e\[<[\d;]>*m> /, '***', :g );
say $str; # abc***def***ghi
如果需要复用 myregex2,可以把相关匹配逻辑移出 look-behind,或先用内联模式验证结果。具体改法取决于要替换的文本范围。使用子规则时,应确认它在 <?after ...> 中的行为是否与直接内联相同。
注意事项
这个结论针对题目展示的 Raku/Rakudo 行为。输入没有提供 Rakudo 版本,因此无法判断某个特定版本是否已修复。升级后如果仍使用子规则写法,建议用同一段最小代码确认匹配位置和替换结果。
备注:内容仅供参考。
