私のファイルには複数の列が含まれており、最初の列はIDに対応しています。ファイル全体でIDが一度だけ表示される場合(最初の列)、行を削除したいと思います。 IDが何度も表示される場合は、その行をファイルに保存したいと思います。 IDはAで始まる文字(時には数字)で構成されています(他のすべての文字/数字はランダムな順序です)。たとえば、A2SGWS7CUGU8GB
私が持っているなら:
# id #column 2 ...
A2SGWS7CUGU8GB
A2SGWS7CUGU8GB
ADE8GST9URWPOS
ABXLMWJCQFGVXV
A2SGWS7CUGU8GB
ADE8GST9URWPOS
と を含む行はABXLMWJCQFGVXV
一度だけ表示されるので、削除したいと思います。どうすればいいですか?
ベストアンサー1
まず、保持したいすべての冗長IDが返されます。
$ awk '{ print $1 }' <file | sort | uniq -d
A2SGWS7CUGU8GB
を使用して、最初のスペースで区切られたフィールド(ID)を抽出してこれを実行しますawk
。その後、それらをソートしてuniq -d
重複したIDのみを出力するために使用されます。
その後、これらの(この場合は単一の)IDを使用して元のファイルからその行を抽出できます。まず、次のようにソートする必要がありますjoin
。
$ join <( awk '{ print $1 }' <file | sort | uniq -d ) <( sort file )
A2SGWS7CUGU8GB
A2SGWS7CUGU8GB
A2SGWS7CUGU8GB
シェルが<(...)
一時ファイルを使用したプロセスの置き換えをサポートしていない場合は、一時ファイルを使用して2つのステップでこれを実行できます。
$ sort -o file.sorted file
$ awk '{ print $1 }' <file | sort | uniq -d | join - file.sorted
A2SGWS7CUGU8GB
A2SGWS7CUGU8GB
A2SGWS7CUGU8GB
使用ただ awk
、これは次のように行うことができます。
$ awk 'NR == FNR { count[$1]++; next } count[$1] > 1' file file
A2SGWS7CUGU8GB
A2SGWS7CUGU8GB
A2SGWS7CUGU8GB
コードはファイルを2回読み取るため、コマンドラインでファイルを2回参照しますawk
。
最初は、連想配列がcount
各IDの発生回数で満たされ、第2に、IDが複数回発生する各行が出力される。
上記の2つの方法の違いは、awk
最後のコマンドが元のデータの順序を維持しますが、一意のIDの数に比例してメモリを消費することです。最初のアプローチはソートされた結果を生成するため、より適している可能性があります。とても大きいデータ。
ヘッダー行を保持するには、コマンドを少し変更する必要があります。
$ join <( awk '{ print $1 }' <file | sort | uniq -d ) <( sort file ) | cat <(head -1 file) -
または
$ sort -o file.sorted file
$ awk '{ print $1 }' <file | sort | uniq -d | join - file.sorted > file.noheader
$ head -1 file | cat - file.noheader
または
$ awk 'NR == 1 ; NR == FNR { count[$1]++; next } count[$1] > 1' file file