Unixでファイル内の重複行を削除する方法はありますか?
sort -u
およびuniq
コマンドを使用して実行できますが、sed
またはawk
を使用します。それは可能ですか?
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と評価され、行は出力に書き込まれません。
から 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'
@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
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;」。
Vim(Vi compatible)を使用する代替方法:
ファイルから重複した連続した行を削除します。
vim -esu NONE +'g/\v^(.*)\n\1$/d' +wq
ファイルから重複した、連続していない、空でない行を削除します。
vim -esu NONE +'g/\v^(.+)$\_.{-}^\1$/d' +wq