awk を使用してパターンの一部または全部を一致させます。

awk を使用してパターンの一部または全部を一致させます。

awkのマルチパターンマッチングについて理解できない小さな問題があります。次のawk行があります。

awk '/pat1/{v1=$4; next} /pat2/{v2=$5; next} /pat3/{v3=$6;next} /pat4/{v4=$5; print v1,"    ",v2,"    ",v3"    ",v4}' myfile.out

これはすべて一致するため、私が望む結果(各一致に対して1行に数学結果を印刷)を提供します。パターンの1つが存在しない場合は、何も一致しません。

したがって、すべてが一致すると、期待した結果が得られます。

pat1    pat2    pat3    pat4
pat1    pat2    pat3    pat4
pat1    pat2    pat3    pat4
pat1    pat2    pat3    pat4
.
.
.

各行ごとにpatX異なる値があります!

このスペースを空にしていないように見える場合は、awkにこれらのパターンを見つけるように指示する方法はありますか?

たとえば、最初のインスタンスで更新されている文書にpat3まだ存在しない場合は、次のようにします。pat4

pat1    pat2    
pat1    pat2   pat3    ------> (here let's assume that pat3 has made an appearange)
pat1    pat2   pat3    pat4 ------> (here pat4 started to appear too)
pat1    pat2   pat3    pat4
pat1    pat2   pat3    pat4
.
.
.

awkでできますか?

編集:以下は私が直面している2つの例のシナリオです。私のファイルは空の状態で始まり、いくつかのパターンをフィルタリングする必要があるデータで埋められます。すべてのパターンが最初から現れるわけではありません。したがって、ファイルは次のように始まります。

some text here pat1
some more text here

some more text here pat2

some more text here and pat3


上記のawkコマンドを使用すると、pat4まだ存在しないため、空の結果が得られます。時間が経つと結局現れます。

some text here pat1
some more text here

some more text here pat2

some more text here and pat3

some more text here pat4

some text here pat1
some more text here

some more text here pat2

some more text here and pat3

some more text here pat4

some text here pat1
some more text here

some more text here pat2

some more text here and pat3

some more text here pat4

このコマンドの結果はawk期待どおりに表示されます。

pat1      pat2      pat3     pat4
pat1      pat2      pat3     pat4
pat1      pat2      pat3     pat4

しかし、最初に得たかった結果は次のとおりです。

pat1    pat2    pat3   

今より明確になることを願っています。 (上記のawkコマンドをより簡単にするために再構築してテストしました。)

答え1

次のようなものが必要なようです。

$ cat tst.awk
BEGIN { OFS="     " }

{ sub(/\r$/,"") }

( ($NF ~ /pat1/) && (state == 0) ) ||
( ($NF ~ /pat2/) && (state == 1) ) ||
( ($NF ~ /pat3/) && (state == 2) ) ||
( ($NF ~ /pat4/) && (state == 3) ) {
    v[++state] = $NF
}

state == 4 {
    print v[1], v[2], v[3], v[4]
    state = 0
}

$ awk -f tst.awk file
pat1     pat2     pat3     pat4
pat1     pat2     pat3     pat4
pat1     pat2     pat3     pat4

答え2

おそらくEND句を使用して結果を印刷することもできます。

    awk '/pat1/{v1=$4; next} /pat2/{v2=$5; next} /pat3/{v3=$6; next} /pat4/{v4=$5;} END{ print v1,"    ",v2,"    ",v3"    ",v4 }' myfile.out

答え3

私の質問に@EdMortonの答えを適用しようとしている間、私は以前に誰かから必要な情報を見つけました。ワイヤー彼は答えを提供し、問題を完全に解決しました。これが私の解決策です。

awk '/pat1/{v1=$4; next}{v1="xxx"} /pat2/{v2=$5; next}{v2="xxx"} /pat3/{v3=$6;next}{v3="xxx"} /pat4/{v4=$5}{v4="xxx"} {print v1,"    ",v2,"    ",v3"    ",v4}' myfile.out

パターンの1つがまだ存在しない場合は、xxxその場でパターンを探してみましょう。xxx単一の空白文字または異なる値に置き換えることができます。

すべてのアドバイスと助けに感謝!

PS:時々問題を説明するために入力例を提供するのは簡単ではないことがわかりました。これで失望したらすみません!

答え4

Raku(以前のPerl_6)の使用

raku -e 'my @a; my @pat = <<pat1 pat2 pat3 pat4>>; for lines() { for @pat -> $i { @a.push( m[$i] // " __ " ) };}; .put unless $_ eq " __   __   __   __ " for @a.rotor(4);'

トリッキーな質問のためラクから回答しました。 1行に必要な項目が2つ以上含まれている場合はどうなりますかpattern?それともpattern誤動作がありますか?以下のコードはこれらのケースを処理します(パターンが見つからない行も削除します)。

サンプル入力の最後の数行とサンプル出力の最後の数行から抽出されたパターンを見てください。 (以下の例では空行を削除しました。)

入力例:

some text here pat1
some more text here
some more text here pat2
some more text here and pat3
some more text here
some text here pat1
some more text here
some more text here pat2
some more text here and pat3
some more text here pat4
some text here pat1
some more text here
some more text here pat2
some more text here and pat3
some more text here pat4
some more text here pat1 pat2
some more text here pat1 pat2 pat3 pat4

出力例:

pat1  __   __   __ 
 __  pat2  __   __ 
 __   __  pat3  __ 
pat1  __   __   __ 
 __  pat2  __   __ 
 __   __  pat3  __ 
 __   __   __  pat4
pat1  __   __   __ 
 __  pat2  __   __ 
 __   __  pat3  __ 
 __   __   __  pat4
pat1 pat2  __   __ 
pat1 pat2 pat3 pat4

注:一般的な状況は次のとおりです。いいえ上記のコードは、行の複数のコピーで単一のパターンが見つかった場合を処理します。上記のコードには、発生回数を計算するメカニズムはなく、パターンが「表示されているか」だけを伝えます。以下の例:

echo "text here pat2 pat2 pat2 pat4" | raku -e 'my @a; my @pat = <<pat1 pat2 pat3 pat4>>; for lines() { for @pat -> $i { @a.push( m[$i] // " __ " ) };}; .put unless $_ eq " __   __   __   __ " for @a.rotor(4);'

繰り返しパターン出力:

__  pat2  __  pat4

http://raku.org

関連情報