データを並べ替えずに一意の結果のみを取得する方法は?


40
$ cat data.txt 
aaaaaa
aaaaaa
cccccc
aaaaaa
aaaaaa
bbbbbb
$ cat data.txt | uniq
aaaaaa
cccccc
aaaaaa
bbbbbb
$ cat data.txt | sort | uniq
aaaaaa
bbbbbb
cccccc
$

必要な結果は、元のファイルのすべての行表示して、ファイル内のステートメントの元の順序を維持しながら、(連続したものだけでなく)すべての重複を削除することです

ここで、この例では、実際に探していた結果は

aaaaaa
cccccc
bbbbbb

uniq一般的にこの一般化された操作を実行するにはどうすればよいですか?

回答:


54
perl -ne 'print unless $seen{$_}++' data.txt

または、次の無駄な使用がcat必要な場合

cat data.txt | perl -ne 'print unless $seen{$_}++'

ここだawkPerlを持たないシステムのための翻訳は、:

awk '!seen[$0]++' data.txt
cat data.txt | awk '!seen[$0]++'

3
少し短いawkスクリプトは{ if (!seen[$0]++) print }
camh

1
@fred、あなたのファイルが本当に巨大でない限り、どちらのバージョンも実行するよりも入力に時間がかかります。
cjm

8
awkのバージョンが出たままでも、短くすることができifprint:、括弧、中括弧をawk '!seen[$0]++'
ゴードンDavisson

2
@Legate、これは私たちが見たすべての行を記録している配列の名前です。'!LarryWall[$0]++'すべてのawkケアに変更することもできますが、「見える」ことは人々がプログラムをよりよく理解するのに役立ちます。
cjm

1
@Sadi、それは本当にコメントではなく質問として尋ねられるべきだった。ただし、そのファイルの行の一部はスペースで終わり、一部は終わりません。これらのコマンドは、末尾の空白を含む行全体を重要と見なします。
cjm

13

johnには次のツールがありますunique

usr@srv % cat data.txt | unique out
usr@srv % cat out
aaaaaa
cccccc
bbbbbb

単一のコマンドラインで追加のツールなしで同じことを実現するには、もう少し複雑です。

usr@srv % cat data.txt | nl | sort -k 2 | uniq -f 1 | sort -n | sed 's/\s*[0-9]\+\s\+//'
aaaaaa
cccccc
bbbbbb

nlプリントは、私たちがそうならば、ラインの前に数字を行sort/ uniqその背後に、我々は行の元の順序を復元することができます。sedあとで行番号を削除するだけです;)


同じことができる一般的なLinuxコマンドの組み合わせはありますか?
レーザー

7
「データを並べ替える必要がない」ことで何を逃しましたか
トーター

@Totor- menkusの同様のコメントへの返信をご覧ください。@binfalse-2番目のソリューションは機能しません(この簡単なサンプルでは機能するかもしれませんが、実際の入力では機能しません)。修正してください。たとえば、これは常に機能するはずですnl -ba -nrz data.txt | sort -k2 -u | sort | cut -f2
。– don_crissti

6

私はこれを使用することを好みます:

cat -n data.txt | sort --key=2.1 -b -u | sort -n | cut -c8-

cat -n 行番号を追加し、

sort --key=2.1 -b -u (追加された行番号の後の)2番目のフィールドでソートし、先頭の空白を無視して、一意の行を保持します

sort -n 厳密な数値順に並べ替えます

cut -c8- 列8からEOLまでのすべての文字を保持します(つまり、含めた行番号を省略します)


5
>データをソートせずに独自の結果のみを取得する方法は?>データを並べ替える必要なし
Jan Wikholm

7
「データを並べ替える必要なし」はタイトルにのみ表示されます。実際の必要性は、「ファイル内のステートメントの元の順序を維持しながら、(連続したものだけでなく)すべての重複を削除して元のファイルのすべての行を表示する」ことです。
メンクス

1
@menkusキーは「ファイル内のステートメントの元の順序を維持しながら」です。この答えはそれを達成しません。
アンドリューフェリエ

2

Perlには、という関数を含む使用可能なモジュールがありますuniq。したがって、Perlの配列にデータをロードした場合、このような関数を呼び出すだけで一意になりますが、元の順序は維持されます。

use List::MoreUtils qw(uniq)    
@output = uniq(@output);

このモジュールの詳細については、List :: MoreUtilsをご覧ください。


これは、500 GBなどの巨大なファイルを処理できますか?
少年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.