使用 Damian Conway 的优秀Regexp::Debugger,我尝试了这个:
perl -MRegexp::Debugger -E '$_ = "a"; s/a*/e/g; say'
并得到这个输出,以防它让事情变得更清楚,以事件记录模式显示。通过替换运行的第一遍匹配产生以下事件集:
a | a* | Starting regex match
a | a* | Trying a literal character zero-or-more times (as many as possible)
| a* | Matched
| | Regex matched in 3 steps
这表明“a”第一次匹配,它被“e”替换。
第一次完成匹配后,调试器让我从同一个程序运行第二个匹配:
| <~~ | Back-tracking in regex
| a* | Back-tracked and restarting regex match
| a* | Trying a literal character zero-or-more times (as many as possible)
| a* | Matched
| | Regex matched in 3 steps
这表明原始“a”(现在的“e”)之后的“”第二次匹配并替换为“e”。
不幸的是,要么我不知道如何读取输出,要么 Regexp::Debugger 在这一点上感到困惑或其他什么,但它再次重复,但没有进行替换。
| <~~ | Back-tracking in regex
| a* | Back-tracked and restarting regex match
| a* | Trying a literal character zero-or-more times (as many as possible)
| a* | Matched
| | Regex matched in 3 steps
无论如何,Perl 已经匹配了第三次并且出于某种原因决定这次不进行替换,或者 Regexp::Debugger 或者我只是感到困惑。
编辑:我通过查看perldoc perlre解决了我的困惑:
“更高级别的循环在迭代之间保留了一个额外的状态:最后一个匹配是否为零长度。为了打破循环,零长度匹配之后的下一个匹配被禁止长度为零。这个禁止与回溯交互(参见“回溯”),因此如果最佳匹配的长度为零,则选择次佳匹配。”