Ü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 mituniq -c
verbunden. - Beachten Sie, dass
sort -u
war Teil der 7. Ausgabe von UNIX, circa 1979. Versionen vonsort
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 Befehlip
. - +1 für “ 9 mal 10 I ‚ m leitet tatsächlich an
uniq -c
“ (und möglicherweise noch einmal ansort -nr | head
weiterleiten). Ich habe mich gefragt, wassort | uniq
in Vim entspricht, als ich herausfand, dass Vim den Befehl:sort u
hat. Und TILsort -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 vonsort -n -u
als Duplikate angesehen, von ersteren jedoch nicht!echo -e 'test \n test' | sort -n -u
gibttest
zurück, aberecho -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 anuniq
ü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 ٠١٢٣, sodasssort -u
nur jeweils eines von ihnen behält, während füruniq
(nicht GNUuniq
, dasstrcoll()
verwendet (außer bei-i
)), ① ist anders von ② und 0123 verschieden von ٠١٢٣, daher würdeuniq
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 esstrcmp()
egal ist über Zeichen, da nur Byte-zu-Byte-Vergleiche durchgeführt werden. Dies ist ein weiterer Grund, warumsort -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 vonsort
gibt das first eines gleichen Laufs (siehe Manpage). Somit nimmtsort -fu
das erste Auftreten jeder eindeutigen Zeile ohne Berücksichtigung der Groß- und Kleinschreibung auf. Die Logik, diesort
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