当trans
方法与诸如/^/
之类的正则表达式一起使用时,它将挂起并且无法再返回!
for (-9, -6 ... 0, 2 , 4 ... 10).rotor( 2 => -1) {
.join(',').trans(/^/ => '[', /$/ => ')' ).say;
}
我对它进行了打印,以打印出以下内容:
[-9,-6)
[-6,-3)
[-3,0)
[0,2)
[2,4)
[4,6)
[6,8)
[8,10)
但是它只是烂透了,似乎不再返回了。正如Raku文档所说,“用一个或多个字符替换一个或多个字符”。看来trans
必须至少使用一个字符:
> '123abc345'.trans( /<?after 34> 5$/ => '-')
123abc34-
> '123abc345'.trans( /<?after 34> 5/ => '-')
123abc34-
> '123abc345'.trans( /<?after 345> $/ => '-')
123abc345
> '123abc345'.trans( /^ \d+ <( \w+ )> $/ => '-')
123-
答案 0 :(得分:4)
我同意它必须使用一个字符。
来自a doc I've written on trans
:
如果左侧的匹配项之一为空字符串或正则表达式,并且没有其他匹配项在输入字符串的给定位置匹配,则
.trans
进入无限循环。
也来自该文档:
[此文档]可能是朝着更新官方文档和/或清理相关规范测试和/或功能迈出的一步。
虽然我发现trans
的几个问题可能涉及错误,但以上是我在文档中确定的唯一内容。 (我在一个奇怪的地方提到了这个问题。确实,文档组织有点奇怪。我认为我当时对跨语言工作感到厌倦,并打算再次返回该语言以取得进一步的进展,但忘记了直到您问了一个问题。)
无论如何,我只是searched rakudo issues on GH和rt,并且两个队列中都没有匹配的错误。
我认为,至少在trans
根本不使用任何正则表达式并且仅有一个空的 string 匹配器导致无限循环的情况下,它值得一个错误报告。 (零长度匹配 regex 导致循环的情况可能是一个单独的错误,应该通过修改regex引擎代码来解决。我不确定。)
无论哪种方式,如果您要提交问题,请链接到此SO,以便人们也可以接触我的翻译文档。
让我们以正则表达式/^/
开头-匹配字符串的开头-使用非trans
构造来确认其是否正确:
my $foo = 'x';
say $foo ~~ s/^/end/; # 「」
say $foo; # endx
因此/^/
匹配;这是零长度的匹配/捕获; s///
构造将插入替换字符串。一切似乎都很好。
trans
的行为要复杂得多。这是一个严重的“工具化”示例,其匹配模式与您的示例非常接近,并且也是trans
的一部分:
sub start-regex ($which,$/) {
say "start regex $which, ++count = {++$count}, .pos = {$/.pos}"
}
sub end-regex ($which,$/) {
say "end regex $which, .pos = {$/.pos}, matched = '$/' \n"
}
sub replace ($which,$/) {
say "regex $which replaces $/ at .pos = $/.pos()"; $which
}
my $foo = 'x';
my $count;
say $foo.trans:
/ { start-regex 1, $/ } ^ { end-regex 1, $/ } /
=> { replace 1, $/ },
/ { start-regex 2, $/ } . <?{ $count > 0 }> $ { end-regex 2, $/ } /
=> { replace 2, $/ }
这将显示:
start regex 1, ++count = 1, .pos = 0
end regex 1, .pos = 0, matched = ''
start regex 2, ++count = 2, .pos = 0
end regex 2, .pos = 1, matched = 'x'
regex 2 replaces x at .pos = 1
start regex 2, ++count = 3, .pos = 0
end regex 2, .pos = 1, matched = 'x'
start regex 1, ++count = 4, .pos = 1
start regex 2, ++count = 5, .pos = 1
2
这就是它的作用:
调用并匹配第一个正则表达式。匹配长度为零。
调用并匹配第二个正则表达式。匹配项是一个字符。
确定第二个正则表达式更长,因此获胜。因此,请致电替换人员。
将位置重置为零,并再次调用第二个正则表达式!我不知道为什么。它再次匹配,但是第二次替换是 not 。
最后,现在位置增加了一个,它将再次尝试两个正则表达式,但是它们都无法匹配。
如果第二个正则表达式的条件从$count > 0
更改为$count > 2
,则情况会大不相同。它进入一个无限循环,开始于:
start regex 1, ++count = 1, .pos = 0
end regex 1, .pos = 0, matched = ''
start regex 2, ++count = 2, .pos = 0
start regex 2, ++count = 3, .pos = 1
regex 1 replaces at .pos = 0
start regex 1, ++count = 4, .pos = 0
end regex 1, .pos = 0, matched = ''
start regex 1, ++count = 5, .pos = 0
end regex 1, .pos = 0, matched = ''
regex 1 replaces at .pos = 0
start regex 1, ++count = 6, .pos = 0
这就是它的作用:
调用并匹配第一个正则表达式。匹配长度为零。
调用第二个正则表达式。条件失败,所以它不会结束。
将.pos
重置为1
(!?)并再次调用第二个正则表达式!我不知道为什么。它再次失败。
调用与 1st 正则表达式对应的替换闭包。为什么?我以为trans
的逻辑是不接受长度为零的正则表达式!
位置未提前 ,然后再次匹配了第一个正则表达式。两次!并且没有尝试匹配第二个正则表达式。然后再次将与第一个正则表达式替换相对应的替换闭包称为 。
现在我们陷入了循环,重复了最后一个要点!
非常奇怪的行为...