Hva er forskjellen mellom “ sort -u ” og “ sort | uniq ”?

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

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 til uniq -c.
  • Merk at sort -u var en del av 7. utgave UNIX, circa 1979. Versjoner av sort 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 om ip kommandoen nå.
  • +1 for » 9 ganger ut 10 I ‘ m faktisk piping til uniq -c » (og kanskje rør igjen til sort -nr | head). Jeg lurte på hva som tilsvarer sort | uniq i Vim da jeg fant ut at Vim har :sort u kommando. Og TIL sort -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 av sort -n -u, men ikke av førstnevnte! echo -e 'test \n test' | sort -n -u returnerer test, men echo -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 til uniq 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 for uniq (ikke GNU uniq som bruker strcoll() (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) mens strcmp() ikke bryr seg om tegn siden den bare sammenligner byte til byte. Så det er en annen grunn til at sort -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 for sort sender ut første av en lik løp (se mann side). Dermed plukker sort -fu den første forekomsten av hver enkelt saksfølsom unik linje. Logikken som sort 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

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *