web-dev-qa-db-ja.com

Unixでファイル内の重複行を削除するにはどうすればよいですか?

Unixでファイル内の重複行を削除する方法はありますか?

sort -uおよびuniqコマンドを使用して実行できますが、sedまたはawkを使用します。それは可能ですか?

114
Vijay
awk '!seen[$0]++' file.txt

seenは、Awkがファイルのすべての行を渡す連想配列です。行が配列にない場合、seen[$0]はfalseと評価されます。 !は論理否定演算子であり、falseをtrueに反転します。 Awkは、式がtrueと評価される行を出力します。 ++seenをインクリメントして、seen[$0] == 1最初に行が見つかった後、seen[$0] == 2、 等々。
Awkは0および""(空の文字列)をtrueにします。 seenに重複する行が配置されている場合、!seen[$0]はfalseと評価され、行は出力に書き込まれません。

251
Jonas Elfström

から http://sed.sourceforge.net/sed1line.txt :(これがどのように機能するか私に尋ねないでください;-))

 # delete duplicate, consecutive lines from a file (emulates "uniq").
 # First line in a set of duplicate lines is kept, rest are deleted.
 sed '$!N; /^\(.*\)\n\1$/!P; D'

 # delete duplicate, nonconsecutive lines from a file. Beware not to
 # overflow the buffer size of the hold space, or else use GNU sed.
 sed -n 'G; s/\n/&&/; /^\([ -~]*\n\).*\n\1/d; s/\n//; h; P'
28
Andre Miller

@jonasのawkソリューションに似たPerlワンライナー:

Perl -ne 'print if ! $x{$_}++' file

このバリエーションは、比較する前に末尾の空白を削除します。

Perl -lne 's/\s*$//; print if ! $x{$_}++' file

このバリエーションは、ファイルをその場で編集します。

Perl -i -ne 'print if ! $x{$_}++' file

このバリエーションでは、ファイルをその場で編集し、バックアップを作成しますfile.bak

Perl -i.bak -ne 'print if ! $x{$_}++' file
12
Chris Koknat

Andre Millerが上に投稿したワンライナーは、入力ファイルが空白行で終わり、charsがない場合のsedの最近のバージョンを除いて機能します。 Macでは、CPUが回転するだけです。

最後の行が空白で文字がない場合の無限ループ

sed '$!N; /^\(.*\)\n\1$/!P; D'

ハングしませんが、最後の行を失います

sed '$d;N; /^\(.*\)\n\1$/!P; D'

説明は sed FAQ の最後にあります:

GNU sedメンテナは、移植性の問題にもかかわらず、
これにより、Nコマンドを印刷に変更します(ではなく
delete)パターン空間は、自分の直感とより一貫していました
「次の行を追加する」コマンドの動作方法について。
変更を支持するもう1つの事実は、「{N; command;}」が
ファイルの行数が奇数の場合、最後の行を削除しますが、
ファイルの行数が偶数の場合、最後の行を印刷します。

Nの以前の動作を使用したスクリプトを変換するには(削除
EOFに到達したときのパターンスペース)と互換性のあるスクリプト
sedのすべてのバージョン、単独の「N;」の変更「$ d; N;」

7
Bradley Kreider

Vim(Vi compatible)を使用する代替方法

ファイルから重複した連続した行を削除します。

vim -esu NONE +'g/\v^(.*)\n\1$/d' +wq

ファイルから重複した、連続していない、空でない行を削除します。

vim -esu NONE +'g/\v^(.+)$\_.{-}^\1$/d' +wq

4
Bohr