Perl:while块中的多个全局"或"分离的正则表达式条件导致无限循环?

Tom*_*lis 5 regex perl loops while-loop

我正在学习Perl并注意到一个相当特殊的怪癖 - 尝试在while循环中匹配多个正则表达式条件之一导致该循环继续进行无穷大:

#!/usr/bin/perl

my $hivar = "this or that";

while ($hivar =~ m/this/ig || $hivar =~ m/that/ig) {
        print "$&\n";
}
Run Code Online (Sandbox Code Playgroud)

该程序的输出是:

this
that
that
that
that
[...]
Run Code Online (Sandbox Code Playgroud)

我想知道为什么会这样?有没有比这更笨拙的变通办法:

#!/usr/bin/perl

my $hivar = "this or that";

while ($hivar =~ m/this|that/ig) {
        print "$&\n";
}
Run Code Online (Sandbox Code Playgroud)

这是我遇到的现实世界问题的简化,虽然我从实际角度对此感兴趣,但我也想知道幕后是什么触发了这种行为.这个问题似乎与Google不兼容.

谢谢!

汤姆

hob*_*bbs 16

问题在于,每个字符串都有一个隐藏的值,而不是每个匹配项,它控制/g匹配将尝试继续的位置,并可通过pos($string).会发生什么:

  1. pos($hivar)为0,/this/匹配位置0并重置pos($hivar)为4.未尝试第二次匹配,因为或运算符已经为真.$&成为"这个"并打印出来.
  2. pos($hivar)是4,/this/无法匹配,因为在4号位或更高位置没有"这个".失败的匹配重置pos($hivar)为0.
  3. /that/匹配在位置6并重置pos($hivar)为10. $&变为"那个"并被打印.
  4. pos($hivar)是10,/this/没有匹配,因为10号位或更高位置没有"这个".失败的匹配重置pos($hivar)为0.
  5. /that/匹配在位置6并重置pos($hivar)为10. $&变为"那个"并被打印.

并且步骤4和5无限重复.

添加c正则表达式标志(告诉引擎pos在失败的匹配时不重置)解决了您提供的示例代码中的问题,但它可能是也可能不是更复杂问题的理想解决方案.

  • 真的很好解释,为你的cookie. (2认同)