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

120

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

Benubird
quelle

Antworten:

120

sort | uniqgab es schon früher sort -uund ist mit einer Vielzahl von Systemen kompatibel, obwohl fast alle modernen Systeme dies unterstützen -u- es ist POSIX. Es ist vor allem eine Reminiszenz an die Tage , wenn sort -unicht existiert (und die Menschen nicht dazu neigen , ihre Methoden zu ändern , wenn die Art und Weise , dass sie wissen , weiter zu arbeiten, schauen Sie sich ifconfiggegen ipAdoption).

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

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 möglicherweise wichtig ist (in modernen Shells gibt es Möglichkeiten, bashdas $PIPESTATUSArray zu ermitteln, aber das stimmte nicht immer).

Chris Down
quelle
31
Ich neige dazu zu verwenden, sort | uniqweil ich 9 mal von 10 tatsächlich anpfeife uniq -c.
Plutor
5
Beachten Sie, dass dies sort -uTeil der 7. Ausgabe von UNIX, circa 1979, war. Versionen sortohne Unterstützung für -usind wirklich archaisch - oder wurden ohne Berücksichtigung des De-facto-Standards vor dem De-jure-Standard von POSIX geschrieben. Siehe auch Stack Overflow Sort & uniq in der Linux-Shell von 2010.
Jonathan Leffler
3
+1 wegen ip. Es ist 2016 und dieser Beitrag im Jahr 2013, aber ich weiß ipjetzt nur über Befehl.
02:22 Uhr
4
+1 für "9-mal aus 10 uniq -c" (und vielleicht noch einmal für " sort -nr | head). Ich habe mich gefragt, was sort | uniqVim entspricht, als ich herausfand, dass Vim das :sort uKommando hat. Und TIL sort -ugibt es auch.
Zhuoyun Wei
Beachten Sie, dass es bei der Verwendung von sort -n | uniqvs. einen Unterschied gibt sort -n -u. Zum Beispiel werden abschließende und führende Leerzeichen sort -n -uvon ersteren als Duplikate angesehen, aber nicht von diesen! echo -e 'test \n test' | sort -n -ugibt zurück test, gibt aber echo -e 'test \n test' | sort -n | uniqbeide Zeilen zurück.
mxmlnkn
46

Ein Unterschied besteht darin, dass uniqes eine Reihe nützlicher zusätzlicher Optionen gibt, z. B. das Überspringen von Feldern zum Vergleichen und das Zählen der Anzahl der Wiederholungen eines Werts. sortDas -uFlag von implementiert nur die Funktionalität des schmucklosen uniqBefehls.

CLF
quelle
3
+0,49 für eine nützliche Antwort, aber ich würde es in etwa so ausdrücken: "Die Ausgabe von sort -ukann nicht übergeben werden uniq, um einige der nützlichen Optionen des letzteren zu verwenden, wie zum Beispiel das Überspringen von Feldern zum Vergleichen und Zählen der Anzahl von Wiederholungen."
l0b0
15
+1 die Neinsager zu kompensieren , weil „es keine Möglichkeit gibt , diese von Art direkt zu tun“ hat die Frage beantworten ...
Izkata
42

Bei POSIX-kompatiblen sorts und uniqs (GNU uniqist derzeit in dieser Hinsicht nicht kompatibel) gibt es einen Unterschied darin, dass sortder Sortieralgorithmus des Gebietsschemas zum Vergleichen von Zeichenfolgen verwendet wird (wird normalerweise strcoll()zum Vergleichen von Zeichenfolgen verwendet), während uniqauf Byte-Wert-Identität geprüft wird (wird normalerweise verwendet strcmp()). .

Das ist aus mindestens zwei Gründen wichtig.

  • In einigen Gebietsschemata, insbesondere auf GNU-Systemen, gibt es verschiedene Zeichen, die gleich sortiert sind. Im Gebietsschema en_US.UTF-8 auf einem GNU-System sortieren beispielsweise alle Zeichen ①②③④⑤⑥⑦⑧⑨⑩ ... und viele andere gleich, da ihre Sortierreihenfolge nicht definiert ist. Die arabischen Ziffern 0123456789 sortieren sich wie die ostarabischen indischen Ziffern (٠١٢٣٤٥٦٧٨٩).

    Denn sort -u① sortiert das Gleiche wie ② und 0123 das Gleiche wie ٠١٢٣, so sort -udass nur eines von jedem erhalten bleibt , während für uniq(nicht GNU uniq, das strcoll()(außer mit -i) verwendet) ① von ② verschieden ist und 0123 von ٠١٢٣ verschieden ist, also uniqalle berücksichtigen würden 4 einzigartig.

  • strcollkann nur Zeichenfolgen gültiger Zeichen vergleichen (das Verhalten ist gemäß POSIX nicht definiert, wenn die Eingabe Sequenzen von Bytes enthält, die keine gültigen Zeichen bilden), während Zeichen strcmp()keine Rolle spielen, da nur ein Byte-zu-Byte-Vergleich durchgeführt wird. Dies ist ein weiterer Grund, warum Sie sort -umöglicherweise nicht alle eindeutigen Zeilen erhalten, wenn einige von ihnen keinen gültigen Text bilden. sort|uniqIn der Praxis ist es wahrscheinlicher, dass Sie aus diesem Grund eindeutige Zeilen erhalten, obwohl dies bei der Nicht-Texteingabe noch nicht festgelegt ist.

Abgesehen von diesen Feinheiten wurde bisher noch nicht bemerkt, dass uniqdie gesamte Zeile lexikalisch verglichen wird, während sortder -uVergleich auf der Grundlage der in der Befehlszeile angegebenen Sortierspezifikation erfolgt.

$ 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
Stéphane Chazelas
quelle
9

Ich bevorzuge die Verwendung, sort | uniqda -ues nicht so einfach ist, das Ergebnis zu verstehen, wenn ich versuche, mit der Option (Duplikate entfernen) Duplikate mit gemischten Groß- / Kleinschreibung zu entfernen.

Hinweis: Bevor Sie die folgenden Beispiele ausführen können, müssen Sie die Standard-C-Sortierfolge folgendermaßen 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 getrennt 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 -uOption zum Entfernen von Duplikaten nicht verwendet wird. Verwenden uniqist vorhersehbarer. Das Folgende sortiert und ignoriert zuerst den Fall und übergibt ihn dann an uniq, um die Duplikate zu entfernen.

$ sort -f short | uniq
Apple
apple
Pear
pear
Jerry Marbas
quelle
2
-uMöglichkeit, sortden ersten eines gleichen Laufs auszugeben (siehe Manpage). So sort -funimmt das erste Auftreten eines jeden Fall unempfindliche einzigartigen Line - Up. Die Logik sortzum Entfernen von Duplikaten ist vorhersehbar.
Pallxk
3

Ein weiterer Unterschied, den ich heute herausgefunden habe, besteht darin, dass beim Sortieren nach einem Delimeter sort -udie eindeutige Markierung nur für die Spalte angewendet wird, nach 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
Stefanos Chrs
quelle
Dies wird in einer Antwort von Stéphane Chazelas erwähnt, aber ich mag Ihr Beispiel so +1
roaima
Vielen Dank für den Hinweis auf @roaima, es war nicht sehr klar in dieser Antwort
Stefanos Chrs