次より大きい重複行の削除

次より大きい重複行の削除

したがって、次の形式の入力ファイルがあります。

Hello\tWorld

それから私は利用可能です

awk -F"\t" '!seen[tolower($1)]++'

最初の列に基づいて重複行を削除します。しかし、そのステートメントで条件をどのように設定しますか?つまり、文字列が5回以上使用されている場合は、重複した行のみを削除しますか、それともすべての行を削除しますか?

入力例:

Hello   World
Hello   World
Hello   World
Hello   World
Hello   World
New Example
Hello   World

したがって、上記の例では、column1は5回以上存在するため、予想される出力は次のようになります。

Hello   World
New     Example

または、特定の行を完全に削除するには

New Example

答え1

式は、配列項目が最初に存在するかどうかをテストするブール値です。効果がある!条件を反転するには。しかし、ずっと計算されている

ただテストに慣れてください。バージョン6以降の印刷を拒否します。

awk -F"\t" '++seen[tolower($1)] <= 5'

答え2

どちらの例も入力ファイルを2回読み込みます。最初のステップでは最初の列の数を計算し、2番目のステップでは現在の行を印刷して数と比較します。

  1. 最初の列が5回以上表示される場合は、最初の発生位置を印刷します。

    awk -F'\t' '
      FNR==NR{ seen[tolower($1)]++; next }
      seen[tolower($1)]
      seen[tolower($1)]>5{ delete seen[tolower($1)] }
    ' file file
    

    現在の行は、最初の列が配列()にある場合にのみ印刷されますseen[tolower($1)]。 5回以上表示されると、配列から削除されます。

  2. 最初の列が5回以上表示されたら、その行を削除します。

    awk -F'\t' '
      FNR==NR{ seen[tolower($1)]++; next }
      seen[tolower($1)]<=5
    ' file file
    

    列数が5つ以下の場合にのみ、現在の行を印刷します。

答え3

ファイル全体を配列に保存すると、ファイルを2回読み取ることなくすべての操作を実行できます。つまり、パイプラインで動作します。ファイルを2回読み取るよりも複雑さが高いかどうかは比較しませんでしたが、毎秒約275,000行を処理しています。私は定期的に最大400MBのawk配列を使用するので、データサイズは問題になりません。

入力ファイルのサイズとキー数を表示します。

Paul---) wc  53.txt
 100008  187520 1100108 53.txt
Paul---) cut -f1 53.txt | sort | uniq -c
  12500 Can
  12500 Care
  12500 If
  12500 Major
  12500 Minor
  12500 Not
      5 Oak
  12500 Sample
      1 Spruce
      2 Willow
  12500 With

これは実行とタイミングを示しています。入力データの伝播、残りの行とのキー分離、元のシーケンスの保存を確認するために、いくつかのデバッグも必要です。 Catはパイプ入力を強制するために使用されます。

Paul---) time cat 53.txt | ./5fold
Ln   5590 Num 5 Key :Oak: Oak   Fifth
Ln   8654 Num 2 Key :Willow: Willow Pattern China
Ln  13427 Num 1 Key :Spruce: Spruce Only One
Ln  65309 Num 5 Key :Oak: Oak   Fourth
Ln  70988 Num 5 Key :Oak: Oak   Third
Ln  83982 Num 5 Key :Oak: Oak   Second
Ln  87439 Num 5 Key :Oak: Oak   First
Ln  99977 Num 2 Key :Willow: Willow Weep for Me

real    0m0.359s
user    0m0.324s
sys 0m0.048s

テストしたコードです。

#! /bin/bash

AWK='''
BEGIN { FS = "\t"; nMax = 5; }
function List (Local, j) {
    for (j = 1; j in X; ++j) {
        if (N[K[j]] <= nMax)
            printf ("Ln %6d Num %d Key :%s: %s\n", j, N[K[j]], K[j], X[j]);
    }
}
{ ++N[$1]; K[NR] = $1; X[NR] = $0; }
END { List( ); }
'''
    awk -f <( echo "${AWK}" ) 

関連情報