Oriunde văd pe cineva care are nevoie să obțină o listă sortată, unică, se conectează întotdeauna la sort | uniq
. „Nu am văzut niciodată exemple în care cineva folosește sort -u
în schimb. De ce nu? Care este diferența și de ce este mai bine să folosiți uniq decât steagul unic pentru a sorta?
Comentarii
- aplawrence.com/Unixart/sort-vs-uniq.html
Răspuns
sort | uniq
exista înainte ca sort -u
și este compatibil cu o gamă mai largă de sisteme, deși aproape toate sistemele moderne acceptă -u
– este POSIX. Este în mare parte o revenire până în zilele în care sort -u
nu exista (iar oamenii nu au tendința de a-și schimba metodele dacă modul în care știu continuă să funcționeze, uitați-vă la ifconfig
vs. ip
adoptare).
Probabil că cele două au fost îmbinate, deoarece eliminarea duplicatelor dintr-un fișier necesită sortare (cel puțin, în standard este un caz de utilizare extrem de obișnuit. De asemenea, este mai rapid intern ca urmare a faptului că puteți face ambele operații în același timp (și datorită faptului că nu necesită IPC între uniq
și sort
). Mai ales dacă fișierul este mare, sort -u
va folosi probabil mai puține fișiere intermediare pentru a sorta datele.
Pe sistemul meu Obțin în mod constant rezultate de acest fel:
$ 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
De asemenea, nu maschează codul de returnare al sort
, care poate fi important (în cochilii moderni există modalități de a obține acest lucru, de exemplu, bash
„s $PIPESTATUS
, dar acest lucru nu a fost” t întotdeauna adevărat).
Comentarii
- Tind să folosesc
sort | uniq
deoarece de 9 ori din 10, De fapt, ‘ mă duc launiq -c
. - Rețineți că
sort -u
a făcut parte din ediția a 7-a UNIX, circa 1979. Versiunilesort
withou Asistența pentru-u
sunt cu adevărat arhaice – sau au fost scrise fără atenție la standardul de facto înainte de POSIX ‘ s de jure standard. A se vedea, de asemenea, Stack Overflow Sortare & uniq în Linux shell din 2010. - +1 pentru că din
ip
. Este ‘ s 2016 și această postare în 2013, dar știu doar despre comandaip
acum. - +1 pentru ” de 9 ori 10 I ‘ m canalizând de fapt către
uniq -c
” (și poate încă o dată canalizarea cătresort -nr | head
). Mă întrebam care este echivalentulsort | uniq
în Vim când am aflat că Vim are comanda:sort u
. Și TILsort -u
există, de asemenea. - Rețineți că există o diferență atunci când utilizați
sort -n | uniq
vs.sort -n -u
. De exemplu, spațiile albe de urmărire și de conducere vor fi văzute ca duplicate desort -n -u
, dar nu de primul!echo -e 'test \n test' | sort -n -u
returneazătest
, darecho -e 'test \n test' | sort -n | uniq
returnează ambele linii.
Răspuns
O diferență este că uniq
are o serie de opțiuni suplimentare utile, cum ar fi sărind câmpuri pentru comparație și numărând numărul de repetări ale unei valori. sort
„s -u
implementează doar funcționalitatea comenzii uniq
fără ornamente.
Comentarii
- +0.49 pentru un răspuns util, dar aș spune-o ceva de genul ”
sort -u
nu se poate transmite ‘ launiq
pentru a utiliza unele dintre acestea din urmă ‘ opțiuni utile, cum ar fi sări peste câmpuri pentru comparație și numărarea numărului de repetări. ” - +1 pentru a compensa naysayers, deoarece ” nu există ‘ nici o modalitate de a face acest lucru direct din sortare ” răspunde la întrebare …
Răspuns
Cu POSIX sort
s și uniq
s (GNU uniq
în prezent nu este conformă în acest sens), există o diferență prin faptul că sort
folosește algoritmul de asociere local pentru a compara șirurile (de obicei se va folosi strcoll()
pentru a compara șirurile) în timp ce uniq
verifică identitatea valorii octeților (va folosi de obicei strcmp()
) ¹.
Acest lucru contează din cel puțin două motive .
-
În unele locații, în special pe sistemele GNU, există diferite caractere care sortează la fel. De exemplu, în localizarea en_US.UTF-8 pe un sistem GNU, toate ①②③④⑤⑥⑦⑧⑨⑩ … caracterele² și multe altele sortează la fel, deoarece ordinea lor de sortare nu este definită. 0123456789 cifre arabe sortează la fel ca Eastern Arabic Indic (s).
Pentru
sort -u
, ① sortează la fel ca ② și 0123 la fel ca ٠١٢٣, astfel încâtsort -u
ar păstra doar unul din fiecare, în timp ce pentruuniq
(nu GNUuniq
care foloseștestrcoll()
(cu excepția-i
)), ① este diferit din ② și 0123 diferit de ٠١٢٣, deciuniq
ar considera toate cele 4 unice. -
strcoll
poate compara șiruri de caractere valide (comportamentul este nedefinit conform POSIX atunci când intrarea are secvențe de octeți care nu formează caractere valide) în timp cestrcmp()
nu-i pasă despre caractere, deoarece face doar comparație octet-la-octet. Deci, acesta este un alt motiv pentru caresort -u
poate să nu vă ofere toate liniile unice dacă unele dintre ele nu formează un text valid.sort|uniq
, deși încă nespecificat la introducerea fără text, în practică este mai probabil să vă ofere linii unice din acest motiv.
În afară de aceste subtilități, un lucru care nu a fost remarcat până acum este că uniq
compară linia întreagă lexical, în timp ce sort
„s -u
compară pe baza specificațiilor de sortare date pe linia de comandă.
$ 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
¹ Versiunile anterioare ale specificației POSIX au provocat confuzie, însă prin listarea variabilei LC_COLLATE
ca una care afectează uniq
, care a fost eliminată în ediția din 2018 și comportamentul clarificat în urma acelei discuții menționate mai sus. Consultați eroarea de grup Austin corespunzătoare
² 2019 editați . Cele de atunci au fost remediate, dar peste 95% din punctele de cod Unicode au încă o ordine nedefinită începând cu versiunea 2.30 a GNU libc . Puteți testa cu 🧙🧚🧛🧜🧝, de exemplu, în versiunile mai noi
Răspunde
Prefer să folosesc sort | uniq
deoarece atunci când încerc să folosesc opțiunea -u
(eliminați duplicatele) pentru a elimina duplicatele care implică șiruri de litere mari, nu este atât de ușor să înțelegeți rezultatul.
Notă: înainte de a putea rula exemplele de mai jos, trebuie să simulați secvența standard de asamblare C făcând următoarele:
LC_ALL=C export LC_ALL
De exemplu, dacă vreau să sortez un fișier și să elimin duplicatele, păstrând în același timp diferitele cazuri de șiruri.
$ 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?)
Această confuzie este rezolvată prin utilizarea opțiunii -u
pentru a elimina duplicatele. Utilizarea uniq
este mai previzibilă. Mai jos, mai întâi sortează și ignoră cazul și apoi îl trimite la uniq
pentru a elimina duplicatele.
$ sort -f short | uniq Apple apple Pear pear
Comentarii
-
-u
opțiuneasort
generează primul de o alergare egală (vezi pagina man). Astfel,sort -fu
preia prima apariție a fiecărei linii unice insensibile la majuscule. Logica pe caresort
o folosește pentru a elimina duplicatele este previzibilă.
Răspuns
O altă diferență pe care am aflat-o astăzi este când sortez pe baza unui delimetru unde sort -u
aplică steagul unic numai pe coloana cu care sortați.
$ 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
Comentarii
- Acest lucru este menționat într-un răspuns de la St é phane Chazelas, dar Îmi place exemplul dvs., așa că +1
- Vă mulțumim că ați subliniat @roaima, nu a fost ‘ foarte clar în acest răspuns