Overalt hvor jeg ser noen trenger å få en sortert, unik liste, rører de alltid til sort | uniq
. Jeg har aldri sett noen eksempler der noen bruker sort -u
i stedet. Hvorfor ikke? Hva er forskjellen, og hvorfor er det bedre å bruke uniq enn det unike flagget for å sortere?
Kommentarer
- aplawrence.com/Unixart/sort-vs-uniq.html
Svar
sort | uniq
eksisterte før sort -u
, og er kompatibel med et bredere spekter av systemer, selv om nesten alle moderne systemer støtter -u
– det er POSIX. Det er stort sett et tilbakeblikk til dagene da sort -u
ikke eksisterte (og folk ikke har en tendens til å endre metodene hvis måten de vet fortsetter å fungere, se bare på ifconfig
vs. ip
adopsjon).
De to ble sannsynligvis slått sammen fordi fjerning av duplikater i en fil krever sortering (i det minste i standarden case), og er et ekstremt vanlig slags bruk. Det er også raskere internt som et resultat av å kunne utføre begge operasjonene samtidig (og på grunn av at det ikke krever IPC mellom uniq
og sort
). Spesielt hvis filen er stor, vil sort -u
trolig bruke færre mellomfiler til å sortere dataene.
På systemet mitt Jeg får konsekvent resultater som dette:
$ 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
Det maskerer heller ikke returkoden til sort
kan være viktig (i moderne skjell er det måter å få dette på, for eksempel bash
«s $PIPESTATUS
array, men dette var ikke» t alltid sant).
Kommentarer
- Jeg pleier å bruke
sort | uniq
fordi 9 ganger av 10, Jeg ‘ Jeg leder faktisk tiluniq -c
. - Merk at
sort -u
var en del av 7. utgave UNIX, circa 1979. Versjoner avsort
withou t støtte for-u
er virkelig arkaisk – eller ble skrevet uten hensyn til de facto-standarden før POSIX ‘ s de jure-standarden. Se også Stack Overflow Sorter & uniq i Linux-skall fra 2010. - +1 fordi av
ip
. Det ‘ s 2016 og dette innlegget i 2013, men jeg vet bare omip
kommandoen nå. - +1 for » 9 ganger ut 10 I ‘ m faktisk piping til
uniq -c
» (og kanskje rør igjen tilsort -nr | head
). Jeg lurte på hva som tilsvarersort | uniq
i Vim da jeg fant ut at Vim har:sort u
kommando. Og TILsort -u
eksisterer også. - Merk at det er forskjell når du bruker
sort -n | uniq
vs.sort -n -u
. For eksempel vil etterfølgende og ledende hvite mellomrom bli sett på som duplikater avsort -n -u
, men ikke av førstnevnte!echo -e 'test \n test' | sort -n -u
returnerertest
, menecho -e 'test \n test' | sort -n | uniq
returnerer begge linjene.
Svar
En forskjell er at uniq
har en rekke nyttige tilleggsalternativer, for eksempel hopper over felt for sammenligning og teller antall repetisjoner av en verdi. sort
«s -u
flagg implementerer bare funksjonaliteten til den usmykket uniq
-kommandoen. p>
Kommentarer
- +0.49 for et nyttig svar, men jeg vil uttrykke det omtrent som » Resultatet av
sort -u
kan ‘ t sendes tiluniq
for å bruke noen av sistnevnte ‘ s nyttige alternativer, for eksempel å hoppe over felt for sammenligning og telle antall repetisjoner. » - +1 for å kompensere for naysayers fordi » der ‘ ingen måte å gjøre dette direkte fra sortering » svarer på spørsmålet …
Svar
Med POSIX-kompatibel sort
s og uniq
s (GNU uniq
er for øyeblikket ikke kompatibel i den forbindelse), der «er en forskjell ved at sort
bruker lokalets sorteringsalgoritme for å sammenligne strenger (vil vanligvis bruke strcoll()
for å sammenligne strenger) mens uniq
sjekker for byteverdiidentitet (vil vanligvis bruke strcmp()
) ¹.
Det betyr noe av minst to grunner .
-
I noen lokaliteter, spesielt på GNU-systemer, er det forskjellige tegn som sorterer likt. For eksempel, i lokalet en_US.UTF-8 på et GNU-system, sorterer alle ①②③④⑤⑥⑦⑧⑨⑩ … tegn ² og mange andre det samme fordi sorteringsrekkefølgen ikke er definert. De arabiske sifrene 0123456789 sorterer det samme som deres Eastern Arabic Indic motstykker (٠١٢٣٤٥٦٧٨٩).
For
sort -u
, ① sorterer det samme som ② og 0123 det samme som ٠١٢٣ såsort -u
beholder bare en av hver, mens foruniq
(ikke GNUuniq
som brukerstrcoll()
(unntatt med-i
)), ① er annerledes fra ② og 0123 forskjellig fra ٠١٢٣, såuniq
vil vurdere alle 4 unike. -
strcoll
kan bare sammenligne strenger med gyldige tegn (oppførselen er udefinert i henhold til POSIX når inngangen har sekvenser med byte som ikke danner gyldige tegn) mensstrcmp()
ikke bryr seg om tegn siden den bare sammenligner byte til byte. Så det er en annen grunn til atsort -u
kanskje ikke gir deg alle de unike linjene hvis noen av dem ikke danner gyldig tekst.sort|uniq
, mens det fremdeles ikke er spesifisert for ikke-tekstinndata, er det i praksis mer sannsynlig å gi deg unike linjer av den grunn.
Foruten disse finessene er en ting som hittil ikke har blitt notert at uniq
sammenligner hele linjen leksikalt, mens sort
«s -u
sammenligner basert på sorteringsspesifikasjonen gitt på kommandolinjen.
$ 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
¹ Tidligere versjoner av POSIX-spesifikasjonen forårsaket forvirring, men ved å oppføre LC_COLLATE
-variabelen som en som påvirker uniq
, som ble fjernet i 2018-utgaven og atferden avklart etter den diskusjonen som er nevnt ovenfor. Se den tilsvarende Austin-gruppefeil
² 2019 rediger . Disse har siden blitt løst, men over 95% av Unicode-kodepunktene har fremdeles en udefinert rekkefølge fra og med versjon 2.30 av GNU libc . Du kan teste med 🧙🧚🧛🧜🧝 i stedet for for eksempel i nyere versjoner
Svar
Jeg foretrekker å bruke sort | uniq
fordi når jeg prøver å bruke alternativet -u
(eliminere duplikater), er det ikke så lett å fjerne duplikater som involverer blandede saksstrenger forstå resultatet.
Merk: før du kan kjøre eksemplene nedenfor, må du simulere standard C-sorteringssekvensen ved å gjøre følgende:
LC_ALL=C export LC_ALL
Hvis jeg for eksempel vil sortere en fil og fjerne duplikater, samtidig som jeg holder de forskjellige tilfellene av strenger forskjellige.
$ 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?)
Denne forvirringen løses ved ikke å bruke alternativet -u
for å fjerne duplikater. Å bruke uniq
er mer forutsigbar. Følgende sorterer først og ignorerer saken, og sender den deretter til uniq
for å fjerne duplikatene.
$ sort -f short | uniq Apple apple Pear pear
Kommentarer
-
-u
alternativet forsort
sender ut første av en lik løp (se mann side). Dermed plukkersort -fu
den første forekomsten av hver enkelt saksfølsom unik linje. Logikken somsort
bruker for å fjerne duplikater er forutsigbar.
Svar
En annen forskjell jeg fant ut i dag, er når jeg sorterer basert på en delimeter der sort -u
bare bruker det unike flagget på kolonnen du sorterer med.
$ 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
Kommentarer
- Dette er nevnt i et svar fra St é phane Chazelas but Jeg liker eksemplet ditt så +1
- Takk for at du påpekte @roaima, det var ikke ‘ t veldig klart i det svaret