0

テキストとアカウント番号が混在するテキストファイルで機能する正規表現をPerlで作成しようとしています。私がやりたいのは、口座番号を再フォーマットすることです。.*特定の行に複数の一致がある場合に、アカウント番号のいずれかの側で一致するためにを使用する際に問題が発生しています。いくつか検索しましたが、答えが見つかりませんでした。将来この落とし穴を回避できるように、誰かが私の正規表現の何が問題になっているのかを説明してくれることを期待しています。

while(<>) {

    s/(.*)\b([0-9]+)\b(.*)/$1xxx\-$2$3/g;
    print;
}

アカウント識別子に置き換えられますが、xxx-機能するまではx'sだけです。

私が抱えている問題は、すべてのオカレンスではなく、最後のオカレンスだけが置き換えられることです。

たとえば、単純なサンプルラインの場合:

First Part 223456 Third Part Fourth Part 113456 Fifth Part Sixth Part

私は期待します:

First Part xxx-223456 Third Part Fourth Part xxx-113456 Fifth Part Sixth Part

しかし、私は得るだけです:

First Part 223456 Third Part Fourth Part xxx-113456 Fifth Part Sixth Part

.* キャプチャグループに他のメタ文字を含めると、問題として絞り込まれますが、ファイルの内容が保証されていないため、すべてを一致させる必要があります。同じ行に複数の口座番号がある場合にのみ発生します。アカウント番号が複数行に表示されている場合は、正常に機能します。

フィードバックをいただければ幸いです

4

4 に答える 4

2

口座番号が単なる数字になる場合は、次のようにします。

s/\b(\d+)\b/xxx-$1/g;

そして、それらが常に6つの数字である場合は、より具体的にしてください:s/\b(\d{6})\b/xxx-$1/g;

于 2013-02-18T17:18:28.587 に答える
2

(.*)入力内のすべての文字を消費すると、バックトラックを開始する必要があります: 1 文字を返し、次のパターンが一致するかどうかをテストし、そうでない場合は別の文字を返し、文字ごとに一致をチェックします。

したがって、貪欲な普遍的な一致を最初の式として配置することで、実際には最後の一致のみを検索するようにエンジンに要求しています。あなたはこれを求めていることを知らなかったかもしれませんが、そうでした.

一般に、正規表現を処理するときは、データについて考える必要があります。一致させたいパターンを指定する能力を最大限に発揮させることができます. そして, 何かがあなたのパターンに一致する場合, それはあなたが望むものである可能性が高いと確信できます. ちなみに, 単語境界指定は良いスタートでした.

正確に 6 桁が必要な場合は、正確に6桁を指定します。

一致の一部として指定する必要がないもう 1 つの理由(.*)は、その外観から、行の他の部分を所定の位置に保つために必要と思われることを行っているためです。ただし、Perl は一致したセクションのみを置換で置き換えます。一致させたい部分以外は何も指定する必要はありません。

したがって、アカウント番号が 6 桁の幅であると仮定すると、これで十分です。

 s/\b(\d{6})\b/xxx-$1/g;

最後に 1 点。何らかの理由で正規表現が最初の一致を見つけた場合、パターンの(.*) に指定すると、行ごとに 1 つの一致しか見つからないことが保証され/g、完全な一致が入力行と等しくなるため、適用されません。

于 2013-02-18T18:31:52.870 に答える
1

私が見る問題は貪欲なマッチング(.*) which in your case will match everything up until the last ([0-9]word boundary)です。これをオフにすれば問題ないと思います(eg. s/(.*?)//g)

以下に小さな例を示します。

while(my $line = <$fh>) {
    $line =~ s/(.*?)\b([0-9]+)\b(.*?)/$1xxx\-$2$3/g;
    print $line;
}

OUTPUT:
First Part xxx-223456 Third Part Fourth Part xxx-113456 Fifth Part Sixth Part
First Part xxx-223456 Third Part Fourth Part xxx-113456 Fifth Part Sixth Part
First Part xxx-223456 Third Part Fourth Part 
First Part xxx-223456
于 2013-02-18T17:35:51.543 に答える
0

否定的な後読みと別の肯定的な先読みを使用する 1 つの方法:

perl -pe 's/(?<!\d)(\d+)(?=\D|$)/xxx-$1/g' <<<"First Part 223456 Third Part Fourth Part 113456 Fifth Part Sixth Part"

次の結果が得られます。

First Part xxx-223456 Third Part Fourth Part xxx-113456 Fifth Part Sixth Part
于 2013-02-18T17:24:12.767 に答える