我想for
使用命名捕获在一个块中进行字符串替换。我期望得到数字1,2,3作为输出。但这是Nil
第一次运行,然后是2和3运行的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 ++提出了一种方法。另一个方法是用大括号({$<nr>}
)包裹替换项。
subst
在Raku尝试调用该subst
例程之前,它会汇总一组要传递给它的参数。
有两个值。第一个是正则表达式。它并没有运行。第二个值是$<nr>
。求值的Nil
原因是,在程序开始时,当前的match对象变量绑定到声称其值为true的对象,Nil
并且任何尝试访问其中的键的值的尝试$<nr>
-也会返回Nil
。因此,在此之前,一切都已经出错了subst
。
一旦Raku汇编了此参数列表,它将尝试调用subst
。它成功并subst
运行。
要获得下一个匹配项,请subst
运行正则表达式。这将更新当前的match对象变量$/
。但是,现在已经太晚了,无法与已经传递给的替换值产生任何区别subst
。
有了match,subst
接下来看一下替换参数。它找到Nil
并采取相应措施。
对于的第二次调用subst
,$<nr>
已采用的第一次调用的值subst
。等等。
$<nr>
@JoKing建议考虑使用S///
。此构造首先评估正则表达式(在第一对/
s之间),然后评估替换(在最后一对/
s之间)。(如果使用其他有效的S
语法,例如,则适用相同的原理S[...] = ...
。)
如果使用subst
,则如上一节中所述,Raku在调用它之前将其参数列表放在一起。它找到一个正则表达式(它不运行)和一个闭包(它也不运行)。然后,它尝试subst
使用这些参数进行调用,并成功执行了该操作。
接下来,subst
开始运行。它已经收到了匹配(正则表达式)和替换(闭包)的代码。
它运行正则表达式作为匹配操作。如果正则表达式返回匹配项,则subst
运行闭包并将其返回的值用作替换。
因此,由于我们从传递$<nr>
为裸值(Nil
即将其冻结为)切换为将其包装在一个封闭的容器中,从而将其评估推迟到将其$/
设置为与填充的<nr>
条目匹配之前,我们解决了该问题。
请注意,这只是工作,因为谁设计/实施subst
为智能/不错的,足以让比赛双方和替代参数是形式Code
(对于比赛和普通封闭的替代正则表达式),如果用户希望这样。然后,它首先运行匹配项,然后,如果已通过替换关闭,则仅运行替换关闭,并使用后一个调用的结果作为最终替换。同样,S///
之所以起作用,是因为它被设计为仅在首次评估替换后评估替换。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句