在 for 循环中用 .subst 替换字符串
String replacement with .subst in a for loop
我想使用命名捕获在 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++ 建议 。另一种方法是用大括号 ({$<nr>}
).
包裹替换
当您的原始代码调用 subst
时会发生什么
在 Raku 尝试调用 subst
例程之前,它会将要传递给它的参数列表放在一起。
有两个值。第一个是正则表达式。 它不是运行。第二个值为 $<nr>
。它的计算结果为 Nil
,因为在程序开始时,当前匹配对象变量绑定到声称其值为 Nil
的对象,并且任何试图访问其中键值的尝试—— $<nr>
-- 也 returns Nil
。所以在 subst
曾经 运行s.
之前,事情已经出了问题
一旦 Raku 收集了这个参数列表,它就会尝试调用 subst
。它成功了,并且 subst
运行s.
要获得下一个匹配项,subst
运行 正则表达式。这将更新当前匹配对象变量 $/
。但是要对已经传递给 subst
.
的替代值产生任何影响已经太迟了
有了匹配项,subst
接下来查看替换参数。它发现它是 Nil
并据此采取行动。
对于 subst
的 second 调用,$<nr>
已采用 first 调用的值subst
个。等等。
延迟计算 $<nr>
的两种方法
@JoKing 建议考虑使用 S///
。此构造首先评估正则表达式(在第一对 /
之间),然后是替换(在最后一对 /
之间)。 (如果您使用其他有效的 S
语法,如 S[...] = ...
,同样的原则也适用。)
如果你使用subst
,那么,如前一节所述,Raku 在调用它之前将参数列表放在一起。它找到一个正则表达式(它没有 运行)和一个闭包(它也没有 运行)。然后它尝试使用这些参数调用 subst
并成功调用。
接下来,subst
开始 运行ning。它已收到 match(正则表达式)和 substitution(闭包)的代码。
它运行将正则表达式作为匹配操作。如果正则表达式 returns 匹配,则 subst
运行 关闭并使用它的值 returns 作为替换。
因此,因为我们从将 $<nr>
作为裸值传递(这意味着它被冻结为 Nil
)切换到将其包裹在闭包中传递,这将其评估推迟到 [=23] =] 已设置为与填充的 <nr>
条目匹配,我们解决了问题。
请注意,这只有效,因为 designed/implemented subst
smart/nice 足以让匹配 和 替换参数成为形式Code
(用于匹配的正则表达式和用于替换的普通闭包)如果用户需要的话。然后 运行 首先 匹配 然后 运行 替换闭包,如果它已经通过了一个,使用后一个调用的 result 作为最终替换。类似地,S///
有效,因为 that 被设计为仅在首次评估替换后才评估替换。
我想使用命名捕获在 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++ 建议 {$<nr>}
).
当您的原始代码调用 subst
时会发生什么
在 Raku 尝试调用 subst
例程之前,它会将要传递给它的参数列表放在一起。
有两个值。第一个是正则表达式。 它不是运行。第二个值为 $<nr>
。它的计算结果为 Nil
,因为在程序开始时,当前匹配对象变量绑定到声称其值为 Nil
的对象,并且任何试图访问其中键值的尝试—— $<nr>
-- 也 returns Nil
。所以在 subst
曾经 运行s.
一旦 Raku 收集了这个参数列表,它就会尝试调用 subst
。它成功了,并且 subst
运行s.
要获得下一个匹配项,subst
运行 正则表达式。这将更新当前匹配对象变量 $/
。但是要对已经传递给 subst
.
有了匹配项,subst
接下来查看替换参数。它发现它是 Nil
并据此采取行动。
对于 subst
的 second 调用,$<nr>
已采用 first 调用的值subst
个。等等。
延迟计算 $<nr>
的两种方法
@JoKing 建议考虑使用 S///
。此构造首先评估正则表达式(在第一对 /
之间),然后是替换(在最后一对 /
之间)。 (如果您使用其他有效的 S
语法,如 S[...] = ...
,同样的原则也适用。)
如果你使用subst
,那么,如前一节所述,Raku 在调用它之前将参数列表放在一起。它找到一个正则表达式(它没有 运行)和一个闭包(它也没有 运行)。然后它尝试使用这些参数调用 subst
并成功调用。
接下来,subst
开始 运行ning。它已收到 match(正则表达式)和 substitution(闭包)的代码。
它运行将正则表达式作为匹配操作。如果正则表达式 returns 匹配,则 subst
运行 关闭并使用它的值 returns 作为替换。
因此,因为我们从将 $<nr>
作为裸值传递(这意味着它被冻结为 Nil
)切换到将其包裹在闭包中传递,这将其评估推迟到 [=23] =] 已设置为与填充的 <nr>
条目匹配,我们解决了问题。
请注意,这只有效,因为 designed/implemented subst
smart/nice 足以让匹配 和 替换参数成为形式Code
(用于匹配的正则表达式和用于替换的普通闭包)如果用户需要的话。然后 运行 首先 匹配 然后 运行 替换闭包,如果它已经通过了一个,使用后一个调用的 result 作为最终替换。类似地,S///
有效,因为 that 被设计为仅在首次评估替换后才评估替换。