it-swarm.com.de

Was ist der Unterschied zwischen "sort -u" und "sort | uniq"?

Überall, wo ich jemanden sehe, der eine sortierte, eindeutige Liste benötigt, leitet er immer zu sort | uniq. Ich habe noch nie Beispiele gesehen, bei denen jemand sort -u stattdessen. Warum nicht? Was ist der Unterschied und warum ist es besser, uniq als das eindeutige Flag zum Sortieren zu verwenden?

126
Benubird

sort | uniq Existierte vor sort -u Und ist mit einer größeren Anzahl von Systemen kompatibel, obwohl fast alle modernen Systeme -u Unterstützen - es ist POSIX. Es ist meistens ein Rückfall in die Zeit, als sort -u Nicht existierte (und die Leute neigen nicht dazu, ihre Methoden zu ändern, wenn die Art und Weise, wie sie wissen, weiterhin funktioniert, schauen Sie sich einfach ifconfig vs. . ip Adoption).

Die beiden wurden wahrscheinlich zusammengeführt, da das Entfernen von Duplikaten in einer Datei (zumindest im Standardfall) sortiert werden muss und ein äußerst häufiger Anwendungsfall für das Sortieren ist. Es ist auch intern schneller, da beide Vorgänge gleichzeitig ausgeführt werden können (und aufgrund der Tatsache, dass nicht IPC zwischen uniq und erforderlich ist) sort). Insbesondere wenn die Datei groß ist, verwendet sort -u wahrscheinlich weniger Zwischendateien, um die Daten zu sortieren.

Auf meinem System erhalte ich durchweg folgende Ergebnisse:

$ 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

Es maskiert auch nicht den Rückkehrcode von sort, was wichtig sein kann (in modernen Shells gibt es Möglichkeiten, dies zu erhalten, zum Beispiel das Array $PIPESTATUS Von bash , aber das stimmte nicht immer).

129
Chris Down

Ein Unterschied besteht darin, dass uniq eine Reihe nützlicher zusätzlicher Optionen bietet, z. B. das Überspringen von Feldern zum Vergleich und das Zählen der Anzahl der Wiederholungen eines Werts. sort 's -u flag implementiert nur die Funktionalität des schmucklosen uniq Befehls.

49
CLF

Mit POSIX-kompatiblen sorts und uniqs (GNU uniq ist derzeit in dieser Hinsicht nicht kompatibel), es gibt einen Unterschied in diesem sort verwendet den Sortieralgorithmus des Gebietsschemas zum Vergleichen von Zeichenfolgen (verwendet normalerweise strcoll() zum Vergleichen von Zeichenfolgen), während uniq auf Bytewertidentität prüft (verwendet normalerweise strcmp()) ¹ .

Das ist aus mindestens zwei Gründen wichtig.

  • In einigen Gebietsschemas, insbesondere auf GNU - Systemen, gibt es verschiedene Zeichen, die gleich sortiert sind. Zum Beispiel im Gebietsschema en_US.UTF-8 auf einem GNU System, alle ①②③④⑤⑥⑦⑧⑨⑩ ... Zeichen² und viele andere sortieren gleich, da ihre Sortierreihenfolge nicht definiert ist. Die arabischen Ziffern 0123456789 sortieren die gleichen wie ihre Gegenstücke Eastern Arabic Indic (٠١٢٣٤٥٦٧٨٩).

    Für sort -u Sortiert ① dasselbe wie ② und 0123 dasselbe wie ٠١٢٣, sodass sort -u Nur jeweils eines davon behält, während für uniq (nicht GNU uniq, das strcoll() verwendet (außer bei -i)), ① unterscheidet sich von ② und 0123 von ٠١٢٣, also würde uniq Betrachten Sie alle 4 als einzigartig.

  • strcoll kann nur Zeichenfolgen gültiger Zeichen vergleichen (das Verhalten ist gemäß POSIX undefiniert, wenn die Eingabe Folgen von Bytes enthält, die keine gültigen Zeichen bilden), während strcmp() sich nicht um Zeichen kümmert da es nur einen Byte-zu-Byte-Vergleich durchführt. Dies ist ein weiterer Grund, warum sort -u Möglicherweise nicht alle eindeutigen Zeilen enthält, wenn einige von ihnen keinen gültigen Text bilden. sort|uniq Gibt in der Praxis aus diesem Grund eher eindeutige Zeilen an, obwohl dies bei der Eingabe ohne Text noch nicht angegeben ist.

Neben diesen Feinheiten wurde bisher noch nicht bemerkt, dass uniq die gesamte Zeile lexikalisch vergleicht, während sorts -u Basierend auf der im Befehl angegebenen Sortierspezifikation vergleicht Linie.

$ 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

¹ Frühere Versionen der POSIX-Spezifikation sorgten jedoch für Verwirrung, indem sie die Variable LC_COLLATE Als eine Variable auflisteten, die uniq betraf, die in der Ausgabe 2018 entfernt wurde, und das Verhalten nach dieser oben erwähnten Diskussion klarstellte. Siehe der entsprechende Fehler in der Austin-Gruppe

² 2019 bearbeiten . Diese wurden inzwischen behoben, aber über 95% der Unicode-Codepunkte haben ab Version 2.30 der GNU libc noch eine undefinierte Reihenfolge. Sie können mit ?? ?????????????????? stattdessen zum Beispiel in neueren Versionen

45

Ich bevorzuge die Verwendung von sort | uniq, Da das Ergebnis nicht so einfach zu verstehen ist, wenn ich versuche, die Option -u (Duplikate entfernen) zu verwenden, um Duplikate mit Zeichenfolgen in gemischten Groß- und Kleinschreibung zu entfernen.

Hinweis: Bevor Sie die folgenden Beispiele ausführen können, müssen Sie die Standard-C-Sortiersequenz wie folgt simulieren:

LC_ALL=C
export LC_ALL

Zum Beispiel, wenn ich eine Datei sortieren und Duplikate entfernen möchte, während gleichzeitig die verschiedenen Fälle von Zeichenfolgen unterschiedlich bleiben.

$ 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?)

Diese Verwirrung wird behoben, indem die Option -u Nicht zum Entfernen von Duplikaten verwendet wird. Die Verwendung von uniq ist vorhersehbarer. Im Folgenden wird der Fall zuerst sortiert und ignoriert und dann an uniq übergeben, um die Duplikate zu entfernen.

$ sort -f short | uniq
Apple
apple
Pear
pear
9
Jerry Marbas

Ein weiterer Unterschied, den ich heute herausgefunden habe, besteht darin, nach einem Trennzeichen zu sortieren, bei dem sort -u Das eindeutige Flag nur auf die Spalte anwendet, mit der Sie sortieren.

$ 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
4
Stefanos Chrs