【问题标题】:String replacement with .subst in a for loop在 for 循环中用 .subst 替换字符串
【发布时间】:2020-01-22 19:47:00
【问题描述】:

我想使用命名捕获在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
]

【问题讨论】:

  • 我很好奇。什么是 $ ? (我在 raku 文档中找不到它。)
  • @p6steve named capture
  • docs.raku.org/language/… - 谢谢@valle - 现在找到了!
  • 或许有时考虑使用S///。在这种情况下,你可以做S[.$&lt;nr&gt;=(\d)] = $&lt;nr&gt; given $var
  • @JoKing 不错。我赞成您的评论,然后取消了赞成票,因为我意识到我想检查一些东西(结果并不重要),现在所以不会让我恢复我的赞成票。所以我写这个是为了手动+1你的好建议。我也将它整合到我的答案中。

标签: raku string-substitution


【解决方案1】:

TL;DR$&lt;nr&gt; 的评估推迟到正则表达式评估之后。 @JoKing++ 建议 one way。另一种方法是用大括号 ({$&lt;nr&gt;}) 将替换部分包裹起来。

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

在 Raku 尝试调用 subst 例程之前,它会整理一个要传递给它的参数列表。

有两个值。第一个是正则表达式。 它确实运行。第二个值是$&lt;nr&gt;。它的计算结果为Nil,因为在程序开始时,当前匹配对象变量被绑定到声称其值为Nil 的东西以及任何访问其中键值的尝试——$&lt;nr&gt;—— - 也返回Nil。因此,在 subst 运行之前,此时事情已经出错了。

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

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

有了匹配,subst 接下来查看替换参数。它发现它是Nil 并采取相应的行动。

对于subst第二次 调用,$&lt;nr&gt; 采用了subst第一次 调用的值。以此类推。

推迟评估$&lt;nr&gt;的两种方法

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

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

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

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

因此,因为我们从将 $&lt;nr&gt; 作为裸值传递(这意味着它被冻结到 Nil)切换到将其包裹在闭包中传递,这将其评估推迟到 $/ 设置为匹配项通过填充 &lt;nr&gt; 条目,我们解决了问题。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-07
    • 1970-01-01
    • 1970-01-01
    • 2014-12-14
    • 1970-01-01
    • 2011-02-05
    • 1970-01-01
    相关资源
    最近更新 更多