「sort -u」と「sort |」の違いは何ですか ユニック」?


120

並べ替えられた一意のリストを取得する必要がある人がいるところはどこでも、常にパイプされsort | uniqます。誰かがsort -u代わりに使用する例を見たことはありません。何故なの?違いは何ですか?また、一意のフラグよりもuniqを使用してソートする方が良いのはなぜですか?


回答:


120

sort | uniq前に存在しsort -u、ほとんどすべての近代的なシステムがサポートしていますが、システムの広い範囲と互換性があります-u-それはPOSIXです。これは、主に日に先祖返りだsort -u存在していなかった(と彼らは知っている方法は、ただ見て仕事を続けた場合、人々は彼らの方法を変更する傾向がないifconfigip採用)。

ファイル内の重複を削除するには並べ替えが必要になるため(少なくとも、標準の場合)、この2つはおそらくマージされました。これは、並べ替えの非常に一般的な使用例です。それは(と原因、それは間のIPCを必要としないという事実に、同時に両方の操作を行うことができることの結果として、より高速な内部もあるuniqsort)。特に、ファイルが大きい場合はsort -u、データのソートに使用する中間ファイルの数が少なくなる可能性があります。

私のシステムでは、常に次のような結果が得られます。

$ dd if=/dev/urandom of=/dev/shm/file bs=1M count=100
100+0 records in
100+0 records out
104857600 bytes (105 MB) copied, 8.95208 s, 11.7 MB/s
$ time sort -u /dev/shm/file >/dev/null

real        0m0.500s
user        0m0.767s
sys         0m0.167s
$ time sort /dev/shm/file | uniq >/dev/null

real        0m0.772s
user        0m1.137s
sys         0m0.273s

またsort、重要な可能性のある戻りコードをマスクしません(最近のシェルでは、これを取得する方法があります。たとえば、bash$PIPESTATUS配列ですが、これは常に正しいとは限りませんでした)。


31
使用する傾向があるのはsort | uniq、10回のうち9回は実際にに配管しているからuniq -cです。
Plutor

5
その注意sort -uの1979年バージョンごろ、第7版UNIXの一部であったsortためにサポートしていない-uか、POSIXのデジュール標準の前にデファクトスタンダードに注意せずに書かれた-本当に古風です。スタックオーバーフローも参照してくださいLinuxのシェルで並べ替えとuniqは 2010年から
ジョナサン・レフラー

3
+1のためip。2016年と2013年のこの投稿ですが、ip今はコマンドについてしか知りません。
ダイエンド

4
「9回のうち10回、実際にに配管していますuniq -c」(およびにもう一度配管しますsort -nr | head)の場合は+1 。sort | uniqVimに:sort uコマンドがあることを知ったとき、Vimに相当するものは何だろうと思っていました。TILもsort -u存在します。
Zhuoyun魏

sort -n | uniqvs. を使用する場合は違いがあることに注意してくださいsort -n -u。たとえば、末尾の空白と先頭の空白はsort -n -u、前者によってではなく重複として認識されます!echo -e 'test \n test' | sort -n -uを返しますがtestecho -e 'test \n test' | sort -n | uniq両方の行を返します。
mxmlnkn

46

違いの1つは、uniq比較のためにフィールドをスキップしたり、値の繰り返し回数をカウントしたりするなど、多くの便利な追加オプションがあることです。sort-uフラグは、装飾のないuniqコマンドの機能のみを実装します。


3
+0.49は有用な答えですが、「の出力は、比較のためにフィールドをスキップしたり、繰り返しの数をカウントするなど、後者の便利なオプションの一部を使用するためにsort -u渡すことができませんuniq。」
l0b0

15
「並べ替えから直接これを行う方法はありません」質問に答えているので、反対者を相殺するために+1
...-Izkata

42

POSIXに準拠してsortSとuniqS(GNUはuniqその点では、現在対応していない)、違いがありますようにsort(一般的に使用されます文字列を比較するために、ロケールの照合アルゴリズムを使用strcoll()しながら、文字列を比較するために)uniq、バイト値のアイデンティティのためのチェックが(一般的に使用されますstrcmp()) 。

それは少なくとも2つの理由で重要です。

  • 一部のロケール、特にGNUシステムでは、同じようにソートされるさまざまな文字があります。たとえば、GNUシステムのen_US.UTF-8ロケールでは、並べ替え順序が定義されていないため、すべての①②③④⑤⑥⑦⑧⑨⑩...文字と他の多くの文字が同じように並べ替えられます。0123456789アラビア数字は、東アラビアアラビア語の対応する数字(٠١٢٣٤٥٦٧٨٩)と同じようにソートされます。

    のためにsort -u、①は②と同じようにソートされ、0123はsameと同じなのでsort -u、それぞれを1つだけ保持しますが、uniq(GNU uniqではなくstrcoll()(を除く-i)を使用する)、①は②と異なり、0123は٠١٢٣と異なるため、uniqすべてを考慮します4ユニーク。

  • strcoll有効な文字列のみを比較できます(入力に有効な文字を形成しないバイトシーケンスがある場合の動作はPOSIXによって定義されていません)が、strcmp()バイト単位の比較のみを行うため、文字は気にしません。そのためsort -u、一部の行が有効なテキストを形成しない場合、すべての一意の行が表示されない場合があります。sort|uniq、非テキスト入力ではまだ指定されていませんが、実際には、その理由で一意の行を提供する可能性が高くなります。

これらの微妙な点のほかに、これまで指摘されていない一つのことはそれがあるuniq一方で、辞書的に行全体を比較するsortのは-u、コマンドラインで与えられたソート指定に基づいて比較します。

$ printf '%s\n' 'a b' 'a c' | sort -uk 1,1
a b
$ printf '%s\n' 'a b' 'a c' | sort -k 1,1 | uniq
a b
a c

$ printf '%s\n' 0 -0 +0 00 '' | sort -n | uniq
0
-0
+0
00

$ printf '%s\n' 0 -0 +0 00 '' | sort -nu
0

9

大文字と小文字が混在する文字列を含む重複を削除するために(重複を削除する)オプションsort | uniqを使用しようとすると-u、結果を理解するのが簡単ではないため、使用することを好みます。

注:以下の例を実行する前に、以下を実行して標準C照合シーケンスをシミュレートする必要があります。

LC_ALL=C
export LC_ALL

たとえば、ファイルを並べ替えて重複を削除すると同時に、文字列の異なるケースを区別したい場合。

$ cat short      #file to sort
Pear
Pear
apple
pear
Apple

$ sort short     #normal sort (in normal C collating sequence)
Apple            #the lower case words are at the end
Pear
Pear
apple
pear

$ sort -f short  #correctly sorts ignoring the C collating order
Apple            #but duplicates are still there
apple
Pear
Pear
pear

$ sort -fu short #By adding the -u option to remove duplicates it is 
apple            #difficult to ascertain the logic that sort uses to remove
Pear             #duplicates(i.e., why did it remove pear instead of Pear?)

この混乱は-u、重複を削除するオプションを使用しないことで解決されます。使用uniqはより予測可能です。以下は、最初にケースをソートして無視し、次にそれを渡してuniq重複を削除します。

$ sort -f short | uniq
Apple
apple
Pear
pear

2
-uオプションは、同等の実行の最初sort出力します(manページを参照)。したがって、大文字と小文字を区別しないすべての一意の行の最初の出現をピックアップします。重複を削除するために使用するロジックは予測可能です。sort -fusort
pallxk

3

今日見つけた別の違いは、デリミターに基づいてsort -u並べ替える場合、並べ替える列にのみ一意のフラグを適用することです。

$ cat input.csv
3,World,1
1,Hello,1
2,Hello,1

$ cat input.csv | sort -t',' -k2 -u
1,Hello,1
3,World,1

$ cat input.csv | sort -t',' -k2 | uniq
1,Hello,1
2,Hello,1
3,World,1

これはステファンシャゼラスの回答で言及されていますが、私はあなたの例をとても気に入っています。+ 1
roaima

@roaimaを指摘してくれてありがとう、それはその答えは非常に明確ではなかった
ステファノCHRS
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.