Hvad er forskellen mellem “ sort -u ” og “ sort | uniq ”?

Overalt hvor jeg ser nogen, der har brug for at få en sorteret, unik liste, rører de altid til sort | uniq. Jeg har aldrig set eksempler, hvor nogen bruger sort -u i stedet. Hvorfor ikke? Hvad er forskellen, og hvorfor er det bedre at bruge uniq end det unikke flag til at sortere?

Kommentarer

Svar

sort | uniq eksisterede før sort -u og er kompatibel med en bredere vifte af systemer, selvom næsten alle moderne systemer understøtter -u – det er POSIX. Det er for det meste et tilbagekald til de dage, hvor sort -u ikke eksisterede (og folk ikke har tendens til at ændre deres metoder, hvis den måde, de kender fortsætter med at arbejde, skal du bare se på ifconfig vs. ip adoption).

De to blev sandsynligvis flettet, fordi fjernelse af dubletter i en fil kræver sortering (i det mindste i standarden case), og er et ekstremt almindeligt brugsslag. Det er også hurtigere internt som et resultat af at være i stand til at udføre begge operationer på samme tid (og på grund af det faktum, at det ikke kræver IPC mellem uniq og sort). Især hvis filen er stor, vil sort -u sandsynligvis bruge færre mellemfiler til at sortere dataene.

På mit system 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 vigtigt (i moderne skaller er der måder at få dette på, f.eks. bash “s $PIPESTATUS array, men dette var ikke t altid sandt.

Kommentarer

  • Jeg plejer at bruge sort | uniq fordi 9 gange ud af 10, Jeg ‘ Jeg leder faktisk til uniq -c.
  • Bemærk at sort -u var en del af 7. udgave UNIX, omkring 1979. Versioner af sort withou t support til -u er virkelig arkaisk – eller blev skrevet uden opmærksomhed på de facto-standarden før POSIX ‘ s de jure-standard. Se også Stack Overflow Sorter & uniq i Linux shell fra 2010.
  • +1 fordi af ip. Det ‘ s 2016 og dette indlæg i 2013, men jeg ved kun om ip kommandoen nu.
  • +1 til ” 9 gange ud 10 I ‘ m rør faktisk til uniq -c ” (og måske rør igen til sort -nr | head). Jeg spekulerede på, hvad der svarer til sort | uniq i Vim, da jeg fandt ud af, at Vim har :sort u kommando. Og TIL sort -u findes også.
  • Bemærk, at der er forskel, når du bruger sort -n | uniq vs. sort -n -u. For eksempel ses efterfølgende og førende hvide rum som duplikater af sort -n -u men ikke af førstnævnte! echo -e 'test \n test' | sort -n -u returnerer test, men echo -e 'test \n test' | sort -n | uniq returnerer begge linjer.

Svar

En forskel er, at uniq har en række nyttige yderligere muligheder, såsom springer felter til sammenligning og tæller antallet af gentagelser af en værdi. sort “s -u flag implementerer kun funktionaliteten af den ikke-udsmykkede uniq -kommando. p>

Kommentarer

  • +0.49 for et nyttigt svar, men jeg vil sætte det i retning af ” Output af sort -u kan ‘ t sendes til uniq for at bruge nogle af sidstnævnte ‘ s nyttige indstillinger, såsom at springe over felter til sammenligning og tælle antallet af gentagelser. ”
  • +1 for at udligne naysayers fordi ” der ‘ ikke kan gøre dette direkte fra sortering ” besvarer spørgsmålet …

Svar

Med POSIX-kompatibel sort s og uniq s (GNU uniq er i øjeblikket ikke kompatibel i den henseende), der “er en forskel ved, at sort bruger lokalets sorteringsalgoritme til at sammenligne strenge (bruger typisk strcoll() til at sammenligne strenge) mens uniq kontrollerer for byteværdieidentitet (bruger typisk strcmp()) ¹.

Det betyder noget af mindst to grunde .

  • I nogle lokaliteter, især på GNU-systemer, er der forskellige tegn, der sorterer det samme. For eksempel i en_US.UTF-8-lokaliteten på et GNU-system sorterer alle ①②③④⑤⑥⑦⑧⑨⑩ … tegn² og mange andre ens, fordi deres sorteringsrækkefølge ikke er defineret. De arabiske cifre 0123456789 sorterer det samme som deres Østlige arabiske indikatorer (٠١٢٣٤٥٦٧٨٩).

    For sort -u, ① sorterer det samme som ② og 0123 det samme som ٠١٢٣ så sort -u beholder kun en af hver, mens for uniq (ikke GNU uniq som bruger strcoll() (undtagen med -i)), ① er anderledes fra ② og 0123 forskellig fra ٠١٢٣, så uniq vil betragte alle 4 som unikke.

  • strcoll kan kun sammenligne strenge med gyldige tegn (adfærden er udefineret pr. POSIX, når input har sekvenser af bytes, der ikke danner gyldige tegn), mens strcmp() er ligeglad om tegn, da det kun sammenligner byte til byte. Så det er en anden grund til, at sort -u muligvis ikke giver dig alle de unikke linjer, hvis nogle af dem ikke danner gyldig tekst. sort|uniq, selvom det stadig er uspecificeret ved ikke-input, er det i praksis mere sandsynligt, at det giver dig unikke linjer af den grund.

Foruden disse finesser er en ting, der hidtil ikke er blevet bemærket, at uniq sammenligner hele linjen leksikalt, mens sort “s -u sammenligner baseret på sorteringsspecifikationen givet 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 versioner af POSIX-specifikationen forårsagede forvirring, men ved at angive LC_COLLATE variablen som en, der påvirker uniq, der blev fjernet i 2018-udgaven den adfærd, der blev afklaret efter den ovennævnte diskussion. Se den tilsvarende Austin-gruppefejl

² 2019 rediger . Disse er siden blevet rettet, men over 95% af Unicode-kodepunkter har stadig en udefineret rækkefølge fra version 2.30 af GNU libc . Du kan teste med 🧙🧚🧛🧜🧝 i stedet for for eksempel i nyere versioner

Svar

Jeg foretrækker at bruge sort | uniq fordi når jeg prøver at bruge -u (eliminere duplikater) mulighed for at fjerne duplikater, der involverer blandede sagsstrenge, er det ikke så let at forstå resultatet.

Bemærk: Før du kan køre eksemplerne nedenfor, skal du simulere standard C-sorteringssekvensen ved at gøre følgende:

LC_ALL=C export LC_ALL 

Hvis jeg f.eks. vil sortere en fil og fjerne dubletter, samtidig med at de forskellige tilfælde af strenge er forskellige.

$ 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 forvirring løses ved ikke at bruge indstillingen -u til at fjerne dubletter. Brug af uniq er mere forudsigelig. Nedenstående sorterer først og ignorerer sagen og sender den derefter til uniq for at fjerne dubletterne.

$ sort -f short | uniq Apple apple Pear pear 

Kommentarer

  • -u mulighed for sort udsender første af en lige løb (se mand side). Således sort -fu opfanger den første forekomst af hver enkelt sagsfølsom unik linje. Den logik, som sort bruger til at fjerne dubletter, er forudsigelig.

Svar

En anden forskel, jeg fandt ud af i dag, er når jeg sorterer på basis af en delimeter, hvor sort -u kun anvender det unikke flag i den kolonne, som du sorterer med. “3c8a6f1a83”>

Kommentarer

  • Dette er nævnt i et svar fra St é phane Chazelas men Jeg kan godt lide dit eksempel, så +1
  • Tak fordi du påpegede @roaima, det var ikke ‘ t meget klart i det svar

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *