1

一度に複数のパターンを効率的に照合しようとしていますが、これは原則として非常にうまく機能します。

echo abcdef | awk \
'/abc/ {print "match abc"}
 /def/ {print "match def"}'

さらに、レコード内のすべての出現を一致させたい:

echo abcabc | awk \
'function findall(str, re) {
    while(match(str, re)) {
        print "match", re;
        str = substr(str, RSTART+RLENGTH)
    }
}
{
    findall($0, "abc");
}'

上記のサンプルを複数のパターンに一致するように拡張すると、一連の findall 呼び出しが発生します。

findall($0, "abc");
...
findall($0, "def");

問題は、多くの異なるパターン (>100) では、このアプローチが最初のサンプルほどうまく機能しないことです。パターンが同じオートマトンに終わらないので、これは理にかなっています。

物事を少しスピードアップする方法はありますか?たとえば、複数のパターンで「一致」を提供します。パターン (abc|def) を連結できると思いますが、どのパターンが正確に一致したかという情報が失われます。

更新:すべての出現が一致する必要があります:

abcabc
123
abcxyz

入力データは2 つの一致するレコード(標準の区切り文字を指定)になりますが、パターン "abc" および "xyz" を使用すると、データ全体で 4 つの一致が得られるためです。この投稿の最初のサンプルでは、​​少なくとも3 つの一致が報告されていますが、最初のレコードで「abc」が複数回出現していることを検出できません。

4

1 に答える 1

2

次のようにしたらどうですか。

awk 関数ではなく、パターンをファイルに入れ、各パターンを 1 行に配置します。

例えば

kent$  cat p.txt
abc
def
foo
xxx

次に、ファイルをロードして、awk にマッチング ジョブを実行させることができます。最後に、入力文字列に一致したパターンのみを出力します。

    echo inputString|awk 'NR==FNR{ps[$0]=0;next;}
{for(p in ps)if(match($0,p))ps[p]++;}
END{for(p in ps) if(ps[p]>0)print p" matched"}' p.txt -

もちろん、必要に応じて「-」を入力ファイルに置き換えることができます。

小さなテスト:

kent$  echo "abcdefoobarblah"|awk 'NR==FNR{ps[$0]=0;next;}{for(p in ps)if(match($0,p))ps[p]++;}END{for(p in ps) if(ps[p]>0)print p" matched"}' p.txt -
def matched
foo matched
abc matched

したがって、パターン「xxx」は一致しませんでした。def、foo、abc のみが出力されました。

スクリプトを最適化して短くすることができることに注意してください。たとえば、END{} ブロックを保存し、最初の for ループで出力を行います。ただし、それをどのように行うかについての私の考えを示しています。

OPのコメントの編集

ジョー、私はあなたの質問に一致する時間の要件を見ませんでした. ただし、達成するのは難しくありません。サンプルテキストで以下のテストを参照してください。

kent$  echo "abcabcabcdefoobarblah"|
awk 'NR==FNR{ps[$0]=0;next;}
{for(p in ps){t=$0;ps[p]=gsub(p,"",t);}}
END{for(p in ps) if(ps[p]>0)print p" matched "ps[p]" time(s)"}' p.txt -

出力:

def matched 1 time(s)
foo matched 1 time(s)
abc matched 3 time(s)
于 2012-02-28T10:49:04.353 に答える