「sort -u」と「sort | uniq」の違いは何ですか?

「sort -u」と「sort | uniq」の違いは何ですか?

ソートされた一意のリストを取得する必要がある人を見るたびに、彼らは常にこれをsort | uniq。私はそれが使用される例を見たことがありませんsort -u。なぜできないの?違いは何ですか?ソート時にユニークフラグよりuniqを使用する方が良いのはなぜですか?

答え1

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

答え2

POSIX互換sortsとuniqsの場合(GNUはuniq現在これに関して互換性がありません)違いがありますsortロケールの照合アルゴリズムを使用して、文字列(通常はstrcoll()文字列を比較するために使用される)を比較し、バイトuniq値識別子(一般的に使用されるstrcmp())を確認します。

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

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

    の場合sort -u①は②と同じで、0123は٠١٢٣と同じなので1つだけ維持されsort -u、(uniqGNUを使用しない(除外))の場合①は②と異なり、0123は٠١٢٣と異なるため4つすべて保持されます。一意の項目が考慮されます。uniqstrcoll()-funiq

  • strcollstrcmp()バイト間比較のみを実行するため、文字に関係なく有効な文字の文字列(入力に有効な文字を形成しないバイトシーケンスがある場合はPOSIXに従って定義されていない動作)のみを比較できます。したがって、sort -uその行の一部が有効なテキストを形成しない場合、これはすべての一意の行を提供できない可能性があるもう1つの理由です。sort|uniq、テキスト以外の入力にはまだ指定されていませんが、実際には結果として一意の行を提供する可能性が高くなります。

これらの微妙さとは別に、これまで注目されていないことの1つは、行全体が語彙的uniqに比較されるのに対し、sorts-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

1 POSIX仕様の初期バージョンでは、LC_COLLATE変数を影響を受ける変数としてリストして混乱を引き起こしましたuniq。これは2018年版から削除され、上記の説明に従って動作が明確になりました。バラより対応するオースティングループエラー

²2019年編集。これらの問題は解決されたが、GNU libcバージョン2.30以降、Unicodeコードポイントの95%以上がまだ定義されていない順序があります。。あなたはテストすることができます

答え3

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

答え4

今日私が見つけたもう1つの違いは、区切り文字に基づいてソートするときに一意の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

関連情報