2

インターネットで次の AWK プログラムを見つけ、少し調整して列 $2 を確認しました。

{ a[$2,NR]=$0; c[$2]++ }
END {
    for( k in a ) {

       split(k,b,SUBSEP)

       t=c[b[1]] # added this bit to capture count

       if( b[1] in c && t>1 ) { # added && t>1 only print if count more than 1
         print RS "TIMES  ID" RS c[b[1]] "  " b[1] RS
         delete c[b[1]]
       }

       for(i=1;i<=NR;i++) if( a[b[1],i] ) {
          if(t>1){print a[b[1],i]} # added if(t>1) only print lines if count more than 1
          delete a[b[1],i]
       }
    }
}

次のファイルがあるとします。

abc,2,3
def,3,4
ghi,2,3
jkl,5,9
mno,3,2

コマンドを実行すると、出力は次のようになります。

Command: awk -F, -f find_duplicates.awk duplicates

Output:
TIMES  ID
2  2

abc,2,3
ghi,2,3

TIMES  ID
2  3

def,3,4
mno,3,2

これで問題ありません。

AWK プログラムで何が起こっているのかを理解したいと思います。

最初の行が各行を多次元配列にロードしていることを理解していますか? したがって、ファイルの最初の行は次のa['2','1']='abc,2,3'ようになります。

しかし、私は何をするのか、また??c[$2]++の意味は何かについて少し自信があります。split(k,b,SUBSEP)

誰かがこの AWK プログラムで何が起こっているかを行ごとに説明できれば幸いです。

ありがとう。

4

1 に答える 1

2

インクリメント演算子は、参照された変数の値に 1 を追加するだけです。したがってc[$2]++、 の値を取り、c[$2]それに 1 を追加します。$2isaとwas が 3 以前だった場合c["a"]、その値は4この後になります。したがって、見た各値cの数を追跡します。$2

for (k in a)のキーをループしますa$2最初の行の の値が の場合、"a"の最初の値はk"a","1" (1 は行番号) になります。次回$2は2行目からの値と行番号2などの組み合わせになります。

は、 の複合値からsplit(k,b,SUBSEP)新しい配列を作成します。つまり、基本的に、 に入った複合キーの部分を再構築します。の値は、対応する値が作成されたときの値になり、値は対応する行番号になります。bkab[1]$2ab[2]

最後のループはやや非効率的です。可能なすべての行番号をループし、その ID と行番号のエントリが存在しない場合は、すぐに次の行にスキップします。これは外側のループ内で実行for (k in a)されるため、多数の入力がある場合は何度も繰り返されます (入力行ごとにすべての入力行番号がループされます)。最終出力をインクリメンタルに作成し、 のすべてをループした後にすべてを印刷する方が、追加のメモリを犠牲にしてより効率的aです。おそらく次のようなものです:

END {
    for (k in a) {
        split (k,b,SUBSEP)
        if (c[b[1]] > 1) {
            if (! o[b[1]]) o[b[1]] = c[b[1]] "  " b[1] RS
            o[b[1]] = o[b[1]] RS a[k]
        }
        delete a[k]
    }
    for (q in o) print o[q] RS
}

更新: の早期削除を削除しc[b[1]]ました。

于 2012-09-10T20:40:35.940 に答える