误解perl regexp评估

前端之家收集整理的这篇文章主要介绍了误解perl regexp评估前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
一天的美好时光!
我正在读一本关于perl的书:“编程Perl”由Larry Wall,Tom Christiansen,Jon Orwant撰写.在这本书中,我发现了几个作者没有澄清的例子(或者我当时没有得到).

首先

这仅打印ON.

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

但这打印“嗨”TWICE ??怎么解释?

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

继续经历甚至使事情变得更糟:

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

上面的代码串再次打印ONCE这个可怕的“hi”!
大约一个星期后,我完全理解了一件事 – 我需要帮助:)
所以我请你帮助我.

第二个(这是炸弹!)

$_ = "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.”

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

猜你在找的Perl相关文章