regex - 误解 perl regexp 评估

标签 regex perl

一天中的好时光!
我正在阅读一本关于 perl 的书:Larry Wall、Tom Christiansen、Jon Orwant 所著的“Programming Perl”。在这本书中,我发现了几个作者没有澄清的例子(或者我当时根本不明白)。

首先

这只会打印 hi 一次。

 "adfsfloglig"=~ /.*(?{print "hi"})f/;

但这会打印“嗨”两次?怎么解释?
 "adfsfloglig"=~ /.*(?{print "hi"})log/;

继续实验甚至会让事情变得更糟:
  "adfsfloglig"=~ /.*(?{print "hi"})sflog/;

上面的代码字符串再次只打印了一次这个可怕的“嗨”!
大约一周后,我只完全理解了一件事——我需要帮助:)
所以我请求你帮助我,拜托。

第二个(这是炸弹!)
 $_ = "lothiernbfj";

 m/        (?{$i = 0; print "setting i to 0\n"})
       (.(?{ local $i = $i + 1; print "\ti is $i"; print "\tWas founded $&\n" }))*
       (?{print "\nchecking rollback\n"})
       er
       (?{ $result = $i; print "\nsetting result\n"})
 /x;
 print "final $result\n";

这里$result最后在屏幕上打印的字符数等于 .* 匹配的字符数,但我再也听不懂了。

当打开调试打印(如上所示)时,我看到,$i每次在 $& 中包含新字符时都会增加(字符串的匹配部分)。

到底$i等于 11(字符串中的字符数),则有 7 次回滚,当 .*一次(7 次)从其匹配字符返回,因此发生所有模式的匹配。

但是,该死的魔法,结果设置为 $i 的值!我们没有在任何地方减少这个值!所以$result应该等于11!但事实并非如此。作者是对的。我知道。

拜托,你能解释一下这个奇怪的 perl 代码吗,我很高兴认识?
感谢您的任何答复!

最佳答案

来自 http://perldoc.perl.org/perlre.html 的文档:

"WARNING: This extended regular expression feature is considered experimental, and may be changed without notice. Code executed that has side effects may not perform identically from version to version due to the effect of future optimisations in the regex engine. The implementation of this feature was radically overhauled for the 5.18.0 release, and its behaviour in earlier versions of perl was much buggier, especially in relation to parsing, lexical vars, scoping, recursion and reentrancy."



即使匹配失败,如果正则表达式引擎达到必须运行代码的程度,它也会运行代码。如果代码只涉及分配(局部?)变量和任何允许的操作,回溯将导致它撤消操作,因此失败的匹配将不起作用。但是print操作无法撤消,结果是您可以从失败的匹配中打印字符串。这就是文档警告不要嵌入具有“副作用”的代码的原因。

关于regex - 误解 perl regexp 评估,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17760103/

相关文章:

javascript - 无法让网站显示对象标签

perl - 如何在 Perl 中获得带有时间戳的微秒?

perl - 需要有关 perl 中内存使用的建议

perl - 在 Perl 的一个语句中拆分和分配

c# - 使用 RegEx 从字符串中删除特殊字符

c++ - 使用 C++ 解析 robots.txt 文件

java - 如何在 - 和 ^ 之间或 - 之后获取字符串

java - 为什么这个正则表达式会失败?

c# - 使用正则表达式分割嵌套参数

linux - 将 perl 模块复制到其他机器