raku - 在 for 循环中用 .subst 替换字符串

标签 raku string-substitution

我想在 for 中进行字符串替换使用命名捕获阻止。我希望得到数字 1,2,3 作为输出。但它是Nil第一次运行,然后 1 和 2 用于第二次和第三次运行。如何使用 .subst在循环构造中正确吗?我在使用 map 时看到了相同的行为改为构造 for环形。如果我用固定的字符串值替换,它会按预期工作。

for <a1 b2 c3> -> $var {
    say $var;
    say $var.subst(/.$<nr>=(\d)/, $<nr>); #.subst(/.$<nr>=(\d)/, 'X'); #OK      
}

#`[
This is Rakudo version 2019.11 built on MoarVM version 2019.11   
Output:

a1
Use of Nil in string context
  in block  at test3.pl6 line 3

b2
1
c3
2
]

最佳答案

TL;DR 推迟对 $<nr> 的评估直到评估正则表达式之后。 @JoKing++ 建议 one way .另一种方法是用大括号({$<nr>})包裹替换。

当您的原始代码调用 subst 时会发生什么

在 Raku 尝试调用 subst 之前例程,它将参数列表放在一起传递给它。

有两个值。第一个是正则表达式。它确实 不是 跑。第二个值为 $<nr> .它评估为 Nil因为,在程序开始时,当前匹配对象变量绑定(bind)到声称其值为 Nil 的对象。以及任何访问其中键值的尝试 -- $<nr> -- 也返回 Nil .所以,在 subst 之前,事情已经出了问题。永远运行。

一旦 Raku 组装了这个参数列表,它就会尝试调用 subst .它成功了,subst运行。

要获得下一场比赛,subst运行正则表达式。这将更新当前匹配对象变量 $/ .但是现在对已经传递给 subst 的替换值做出任何改变已经太晚了。 .

火柴在手,subst接下来看看替换参数。它发现它是 Nil并采取相应行动。

第二次调用subst , $<nr>已采用 subst 的第一次调用的值.等等。

推迟评估 $<nr> 的两种方法

@JoKing 建议考虑使用 S/// .此构造首先评估正则表达式(在第一对 / 之间),然后是替换(在最后一对 / 之间)。 (如果您使用其他有效的 S 语法,如 S[...] = ...,则同样的原则适用。)

如果您使用 subst ,然后,如上一节所述,Raku 在调用它之前将它的参数列表放在一起。它找到一个正则表达式(它不运行)和一个闭包(它也不运行)。然后它会尝试调用 subst与这些论点并成功地这样做了。

接下来,subst开始运行。它已收到匹配(正则表达式)和替换(闭包)的代码。

它运行正则表达式作为匹配操作。如果正则表达式返回匹配,则 subst运行闭包并使用它返回的值作为替换。

因此,因为我们从传递 $<nr>作为一个裸值,这意味着它被卡住为 Nil , 传递它包裹在一个闭包中,这将其评估推迟到 $/已设置为与填充的 <nr> 匹配入口,我们解决了问题。

请注意,这仅适用于设计/实现 subst 的人。足够聪明/好到允许匹配和替换参数都是 Code 的形式(匹配的正则表达式和替换的普通闭包)如果用户想要的话。然后它首先运行匹配,然后才运行替换闭包,如果它被传递一个,使用后一个调用的结果作为最终替换。同样,S///之所以有效,是因为它被设计为仅在第一次评估替换后才评估替换。

关于raku - 在 for 循环中用 .subst 替换字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59867250/

相关文章:

io - 在 Perl 6 REPL 中使用 chdir 的奇怪(内部?)默认构造函数错误消息

raku - 如果路径包含非拉丁字符,则出错

raku - 如何使用 perl6 正则表达式元语法 <foo regex>?

ruby - 为什么 String::sub!() 会更改 Ruby 中克隆对象的原始对象?

python - 在 python 中用 re.sub 替换特定的命名组

ruby - 比 gsub(/\d|\W/, "") 更短的删除非字符的方法

module - Perl6 : How to find all installed modules whose filename matches a pattern?

raku - "Too few positionals passed"在带类型捕获的 arg-less 方法中

mysql - 将 sql 模式文件的 git diff 转换为应用/撤消 sql 脚本

Python,上下文相关的字符串替换