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 stattdessen sort -u verwendet. Warum nicht? Was ist der Unterschied und warum ist es besser, uniq als das eindeutige Flag zum Sortieren zu verwenden?

Kommentare

Antwort

sort | uniq existierte, bevor 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ückschritt Bis zu den Tagen, an denen sort -u nicht existierte (und die Leute ihre Methoden nicht ändern, wenn die Art und Weise, wie sie wissen, weiterhin funktioniert, schauen Sie sich einfach vs. ip Annahme).

Die beiden wurden wahrscheinlich zusammengeführt, da das Entfernen von Duplikaten in einer Datei eine Sortierung erfordert (zumindest im Standard) case) und ist ein äußerst häufiger Anwendungsfall. Es ist auch intern schneller, da beide Operationen gleichzeitig ausgeführt werden können (und aufgrund der Tatsache, dass kein IPC zwischen uniq und sort). Insbesondere wenn die Datei groß ist, verwendet sort -u wahrscheinlich weniger Zwischendateien zum Sortieren der Daten.

Auf meinem System Ich erhalte 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 

Außerdem wird der Rückkehrcode von sort nicht maskiert kann wichtig sein (in modernen Shells gibt es Möglichkeiten, dies zu erhalten, z. B. das bash$PIPESTATUS -Array, aber dies war nicht der Fall immer wahr).

Kommentare

  • Ich neige dazu, sort | uniq zu verwenden, weil 9 von 10, Ich ‚ bin tatsächlich mit uniq -c verbunden.
  • Beachten Sie, dass sort -u war Teil der 7. Ausgabe von UNIX, circa 1979. Versionen von sort ohne Sie Die Unterstützung für -u ist wirklich archaisch – oder wurde ohne Beachtung des De-facto-Standards vor POSIX ‚ s jure standard geschrieben. Siehe auch Stapelüberlauf Sortieren Sie & uniq in der Linux-Shell ab 2010.
  • +1 weil von ip. Es ist ‚ s 2016 und dieser Beitrag im Jahr 2013, aber ich kenne jetzt nur den Befehl ip.
  • +1 für “ 9 mal 10 I ‚ m leitet tatsächlich an uniq -c “ (und möglicherweise noch einmal an sort -nr | head weiterleiten). Ich habe mich gefragt, was sort | uniq in Vim entspricht, als ich herausfand, dass Vim den Befehl :sort u hat. Und TIL sort -u existiert ebenfalls.
  • Beachten Sie, dass es einen Unterschied gibt, wenn Sie sort -n | uniq vs. sort -n -u. Zum Beispiel werden nachfolgende und führende Leerzeichen von sort -n -u als Duplikate angesehen, von ersteren jedoch nicht! echo -e 'test \n test' | sort -n -u gibt test zurück, aber echo -e 'test \n test' | sort -n | uniq gibt beide Zeilen zurück.

Antwort

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

Kommentare

  • +0,49 für eine nützliche Antwort, aber ich würde es so etwas wie “ Die Ausgabe von sort -u ‚ kann nicht an uniq übergeben werden, um einige der letzteren ‚ nützliche Optionen, z. B. Überspringen von Feldern zum Vergleichen und Zählen der Anzahl der Wiederholungen. “
  • +1 zum Versetzen der Neinsager, weil “ es ‚ keine Möglichkeit gibt, dies direkt von sort “ beantwortet die Frage …

Antwort

Mit POSIX-kompatiblen sort s und uniq s (GNU uniq ist diesbezüglich derzeit nicht konform), gibt es einen Unterschied in diesem sort wird der Sortieralgorithmus des Gebietsschemas zum Vergleichen von Zeichenfolgen verwendet (normalerweise wird strcoll() zum Vergleichen von Zeichenfolgen verwendet), während uniq prüft auf Bytewertidentität (verwendet normalerweise strcmp()) ¹.

Dies ist aus mindestens zwei Gründen wichtig .

  • In einigen Gebietsschemas, insbesondere auf GNU-Systemen, gibt es verschiedene Zeichen, die gleich sortiert sind. Beispielsweise sortieren im Gebietsschema en_US.UTF-8 auf einem GNU-System alle ①②③④⑤⑥⑦⑧⑨⑩ … Zeichen² und viele andere 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 von ihnen behält, während für uniq (nicht GNU uniq, das strcoll() verwendet (außer bei -i)), ① ist anders von ② und 0123 verschieden von ٠١٢٣, daher würde uniq alle 4 als eindeutig betrachten.

  • strcoll kann nur Zeichenfolgen gültiger Zeichen vergleichen (das Verhalten ist gemäß POSIX undefiniert, wenn die Eingabe Sequenzen von Bytes enthält, die keine gültigen Zeichen bilden), während es strcmp() egal ist über Zeichen, da nur Byte-zu-Byte-Vergleiche durchgeführt werden. 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 Obwohl in der Nicht-Texteingabe noch nicht angegeben, werden in der Praxis aus diesem Grund mit größerer Wahrscheinlichkeit eindeutige Zeilen angezeigt.

Neben diesen Feinheiten wurde bisher nicht bemerkt, dass uniq die gesamte Zeile lexikalisch vergleicht, während sort „s -u vergleicht anhand der in der Befehlszeile angegebenen Sortierspezifikation.

$ 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 auflistete, die uniq betraf und in der Ausgabe 2018 und entfernt wurde Das Verhalten wurde nach der oben erwähnten Diskussion geklärt. Siehe den entsprechenden Austin-Gruppenfehler

² 2019 Bearbeiten Sie . Diese wurden inzwischen behoben, aber über 95% der Unicode-Codepunkte haben ab Version 2.30 der GNU libc immer noch eine undefinierte Reihenfolge. Sie können stattdessen mit 🧙🧚🧛🧜🧝 testen, beispielsweise in neueren Versionen

Antwort

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

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 

Kommentare

  • -u Option von sort gibt das first eines gleichen Laufs (siehe Manpage). Somit nimmt sort -fu das erste Auftreten jeder eindeutigen Zeile ohne Berücksichtigung der Groß- und Kleinschreibung auf. Die Logik, die sort zum Entfernen von Duplikaten verwendet, ist vorhersehbar.

Antwort

Ein weiterer Unterschied, den ich heute herausgefunden habe, besteht darin, nach einem Delimeter 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 

Kommentare

  • Dies wird in einer Antwort von St é Phane Chazelas aber erwähnt Ich mag Ihr Beispiel so +1
  • Vielen Dank für den Hinweis auf @roaima, es war ‚ in dieser Antwort nicht sehr klar

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.