最初の列が重複している場合は、ファイル内の行全体を削除します。

最初の列が重複している場合は、ファイル内の行全体を削除します。

2 つの列と 1000 万行を含むファイルがあります。最初の列には多くの重複値が含まれていますが、列 2 には異なる値があります。重複行を削除し、 を使用して 1 つの行だけを保持したいと思いますawk。注: ファイルは列 1 の値で並べ替えられています。例:

1.123 -4.0
2.234 -3.5
2.234 -3.1
2.234 -2.0
4.432 0.0
5.123 +0.2
8.654 +0.5
8.654 +0.8
8.654 +0.9
.
.
.
.

期待される出力

1.123 -4.0
2.234 -3.5
4.432 0.0
5.123 +0.2
8.654 +0.5
.
.
.
.

答え1

いくつかの方法:

  1. awk

    awk '!a[$1]++' file
    

    これは非常に簡潔に書いたものです:

    awk '{if(! a[$1]){print; a[$1]++}}' file
    

    したがって、現在の最初のフィールド ( $1) が配列内にない場合はa、行を出力し、最初のフィールドを に追加しますa。次にそのフィールドが表示されるときには、配列内にあるため、出力されません。

  2. パール

    perl -ane '$k{$F[0]}++ or print' file
    

    または

    perl -ane 'print if !$k{$F[0]}++' file
    

    これは基本的に と同じですawk-nは、perl に入力ファイルを 1 行ずつ読み込ませ、 で提供されるスクリプトを-e各行に適用させます。 は、-a各行を空白で自動的に分割し、結果のフィールドを配列に保存します@F。最後に、最初のフィールドがハッシュに追加され%k、まだ存在しない場合は、その行が印刷されます。同じことを次のように記述できます。

    perl -e 'while(<>){
                @F=split(/\s+/); 
                print unless defined($k{$F[0]}); 
                $k{$F[0]}++;
             }' file
    
  3. コアユーティリティ

    rev file | uniq -f 1 | rev
    

    この方法は、まず の行を逆にして、file行が 12 345 の場合は 543 21 になるようにします。次に を使用して、uniq -f 1最初のフィールド、つまり 543 がある列を無視します。 内にはフィールドがありますfile。ここで を使用すると、uniq重複する行がフィルタリングされ、各行が 1 つだけ保持されます。最後に、もう一度 を逆にして、行を元の順序に戻します。

  4. GNUソート(提案された(@StéphaneChazelas より)

    sort -buk1,1
    

    フラグ-bは先頭の空白を無視し、 は-u一意のフィールドのみを印刷することを意味します。 は賢いビットです-k1,1-kフラグはソートするフィールドを設定します。 これは、ソート時に POS2 を介して-k POS1[,POS2]フィールドのみを参照することを意味する の一般的な形式を取ります。 つまり、 は最初のフィールドのみを参照することを意味します。 データによっては、次のいずれかのオプションも追加する必要がある場合があります。POS1-k1,1

     -g, --general-numeric-sort
          compare according to general numerical value
     -n, --numeric-sort
          compare according to string numerical value
    

答え2

最初の列の長さが常に 5 文字の場合は、次のようにしますuniq

uniq -w 5 file

そうでない場合は、以下を使用しますawk:

awk '$1!=a{print $0; a=$1}' file

巨大なファイルの場合、最初の方法の方が確実に高速になります。

関連情報