使用一对Perl正则表达式匹配的无限循环

时间:2012-07-29 08:01:55

标签: html regex string perl pattern-matching

我用正则表达式编写了一个小的Perl脚本来获取网站的HTML组件。

我知道这不是一种做这种工作的好方法,但我试图测试我的正则表达式技能。

当使用while循环中的两个正则表达式模式中的任何一个运行时,它会完美运行并显示正确的输出。但是当我尝试检查while循环中的两个模式时,第二个模式每次都匹配,循环无限运行。

我的剧本:

#!/usr/bin/perl -w
use strict;

while (<STDIN>) {

    while ( (m/<span class=\"itempp\">([^<]+)+?<\/span>/g) ||
            (m/<font size=\"-1\">([^<]+)+?<\/font>/g) ) {
        print "$1\n";
    }
}

我正在使用示例输入测试上述脚本:

<a href="http://linkTest">Link title</a>
<span class="itempp">$150</span>
<font size="-1"> (Location)</font>

期望的输出:

$150
(Location)

谢谢!任何帮助将非常感谢!

3 个答案:

答案 0 :(得分:9)

每当全局正则表达式无法匹配时,它将重置下一个全局正则表达式将开始搜索的位置。因此,当您的两个模式中的第一个失败时,它会强制第二个模式再次从字符串的开头看。

可以通过添加/c修饰符来禁用此行为,如果正则表达式无法匹配,则会保持位置不变。

此外,您可以通过删除转义字符来改进您的模式("不需要转义,如果您选择不同的分隔符,则/无需转义)和多余+? 1}}捕获之后。

use warnings在命令行上也比-w好得多。

以下是您的代码的工作版本。

use strict;
use warnings;

while (<STDIN>) {

    while( m|<span class="itempp">([^<]+)</span>|gc
            or m|<font size="-1">([^<]+)</font>|gc ) {
        print "$1\n";
    }
}

答案 1 :(得分:3)

while (<DATA>) {
    if (m{<(?:span class="itempp"|font size="-1")>\s*([^<]+)}i) {
        print "$1\n";
    }
}

__DATA__
<a href="http://linkTest">Link title</a>
<span class="itempp">$150</span>
<font size="-1"> (Location)</font>

答案 2 :(得分:-3)

在匹配之后或匹配期间,您没有更改$_,因此它将始终匹配并进入无限循环。

要修复它,您可以在$_=$';之后添加print,以便在字符串的其余部分再次运行匹配。