1

Perl プログラムでファイルからいくつかのデータ パターンを照合しようとしています。一致は複数の行にまたがる可能性があるため、行区切り記号を未定義にしました。

$/ = undef ;

ここで、一致が複数の行と複数の行にまたがる可能性があるため、smgi 修飾子を使用しています。

if ( $msgText =~ /$msgTypeExpr/smgi )

今、私が抱えている問題は、上記の変数 $msgText を置き換えていないのに変更されることです。

関連するコードは次のとおりです。

open (HANDLE1,"$file") || die "cannot open file \n";
$/ = undef ;
while ( my $msgText = <HANDLE1> )
{
        my $msgTypeExpr = "<city\\W+";

        print "Attempt 1:\n";
        if ( $msgText =~ /$msgTypeExpr/smgi )
        {
                print "matched\n";
        }
        else
        {
                print " not matched \n";
        }

        print "Attempt 2:\n";
        if ( $msgText =~ /$msgTypeExpr/smgi )
        {
                print "matched\n";
        }
        else
        {
                print " not matched \n";
        }
}

テスト入力ファイルは次のようになります。

<city
 name="abc">
</city>

パターンが 2 回一致することが予想されますが、一致するのは 1 回目のみで、2 回目は一致しません。

一致する前に一時変数に割り当てて、その一時変数を使用して一致させることで、この問題を一時的に修正しました。

my $tmpMsgText = $msgText ;

このフォーラムに質問を投稿するのはこれが初めてですので、私が犯したかもしれないエチケットの間違いを許してください。

4

2 に答える 2

2

if (//g)意味がありません。「一致し、一致しなくなるまで一致し続ける場合」?を取り除きgます。

なぜあなたがどちらかを使用しているのかわかりませsm

sパターンに が含まれていないため、 は役に立ちません.

mパターンに^orが含まれていないため、は役に立ちません$


実際には//g、スカラー コンテキストでは反復子として機能します。

$ perl -E'$_ = "abc"; /(.)/g && say $1; /(.)/g && say $1;'
a
b
于 2013-11-14T14:04:00.300 に答える
2

まず第一に、そのようなファイルの読み取りについてはよくわかりません。$/ などの Perl 固有の変数の変更は、次のように local で行う必要があります。

local $/ = undef;

このようにして、変数は現在のスコープでのみ変更されます (したがって、可能性のある遠方でのアクションのバグを排除します)。$/ を undef に設定すると、一度にファイル全体を読み取ることになるため、そこに while ループを配置しても意味がありません。ファイル全体を次のように読みます。

open my $fh, "<", "somefile" or die;
my $content = do { local $/ = undef; <$fh> };

do ブロックは、変更された $/ 値をその 1 つのステートメントのみに制限します (新しいスコープを作成します)。

正規表現の一致について: 正規表現の後の /g 修飾子を削除します。私の記憶が正しければ、最後の正規表現検索位置を記憶し、そこから続行します。また、文字列が変更されたかどうかを検出するために、それらの一致の前後に変数を出力します。変更されていないことがわかります。それ以外の:

if ( $msgText =~ /$msgTypeExpr/smgi )

置く:

if ( $msgText =~ /$msgTypeExpr/smi )
于 2013-11-14T13:02:32.293 に答える