6

WebサイトのHTMLコンポーネントを取得するために、正規表現を使用して小さなPerlスクリプトを作成しました。

この種の仕事をするのは良い方法ではないことは知っていますが、正規表現のスキルをテストしようとしていました。

whileループで2つの正規表現パターンのいずれかを使用して実行すると、完全に実行され、正しい出力が表示されます。しかし、whileループで両方のパターンをチェックしようとすると、2番目のパターンが毎回一致し、ループが無限に実行されます。

私のスクリプト:

#!/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)

ありがとうございました!どんな助けでも大歓迎です!

4

3 に答える 3

9

グローバル正規表現が一致しない場合は常に、次のグローバル正規表現が検索を開始する位置がリセットされます。したがって、2 つのパターンの最初のパターンが失敗すると、2 番目のパターンが文字列の先頭から再度検索されます。

この動作は/c修飾子を追加することで無効にできます。これにより、正規表現が一致しない場合に位置が変更されません。

さらに、エスケープ文字 (エスケープする必要はなく、別の区切り文字を選択した場合は"エスケープする必要はありません) とキャプチャの後の余分な文字を削除することで、パターンを改善できます。/+?

また、コマンドライン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";
    }
}
于 2012-07-29T08:40:06.867 に答える
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>
于 2012-07-29T08:21:12.680 に答える
-3

マッチング後またはマッチング中に変更しなかった$_ため、常にマッチングして無限ループに陥ります。

それを修正するには、$_=$';afterを追加しprintて、文字列の残りの部分で再び一致を実行します。

于 2012-07-29T08:07:55.113 に答える