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).会发生什么:
pos($hivar)为0,/this/匹配位置0并重置pos($hivar)为4.未尝试第二次匹配,因为或运算符已经为真.$&成为"这个"并打印出来.pos($hivar)是4,/this/无法匹配,因为在4号位或更高位置没有"这个".失败的匹配重置pos($hivar)为0./that/匹配在位置6并重置pos($hivar)为10. $&变为"那个"并被打印.pos($hivar)是10,/this/没有匹配,因为10号位或更高位置没有"这个".失败的匹配重置pos($hivar)为0./that/匹配在位置6并重置pos($hivar)为10. $&变为"那个"并被打印.并且步骤4和5无限重复.
添加c正则表达式标志(告诉引擎pos在失败的匹配时不重置)解决了您提供的示例代码中的问题,但它可能是也可能不是更复杂问题的理想解决方案.