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
いくつかの方法:
awk
awk '!a[$1]++' file
これは非常に簡潔に書いたものです:
awk '{if(! a[$1]){print; a[$1]++}}' file
したがって、現在の最初のフィールド (
$1
) が配列内にない場合はa
、行を出力し、最初のフィールドを に追加しますa
。次にそのフィールドが表示されるときには、配列内にあるため、出力されません。パール
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
コアユーティリティ
rev file | uniq -f 1 | rev
この方法は、まず の行を逆にして、
file
行が 12 345 の場合は 543 21 になるようにします。次に を使用して、uniq -f 1
最初のフィールド、つまり 543 がある列を無視します。 内にはフィールドがありますfile
。ここで を使用すると、uniq
重複する行がフィルタリングされ、各行が 1 つだけ保持されます。最後に、もう一度 を逆にして、行を元の順序に戻します。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
巨大なファイルの場合、最初の方法の方が確実に高速になります。