Överallt där jag ser någon behöver få en sorterad, unik lista, rör de alltid till sort | uniq
. Jag har aldrig sett några exempel där någon använder sort -u
istället. Varför inte? Vad är skillnaden, och varför är det bättre att använda uniq än den unika flaggan för att sortera?
Kommentarer
- aplawrence.com/Unixart/sort-vs-uniq.html
Svar
sort | uniq
fanns innan sort -u
, och är kompatibel med ett bredare utbud av system, även om nästan alla moderna system stöder -u
– det är POSIX. Det är oftast en throwback till de dagar då sort -u
inte fanns (och människor inte tenderar att ändra sina metoder om det sätt som de vet fortsätter att fungera, titta bara på ifconfig
vs. ip
antagande).
De två slogs sannolikt samman eftersom borttagning av dubbletter i en fil kräver sortering (åtminstone i standarden fall), och är ett extremt vanligt användningsfall. Det går också snabbare internt som ett resultat av att man kan utföra båda operationerna samtidigt (och på grund av att det inte kräver IPC mellan uniq
och sort
). Speciellt om filen är stor kommer sort -u
sannolikt att använda färre mellanfiler för att sortera data.
På mitt system Jag får konsekvent resultat så här:
$ 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 maskerar inte heller returkoden för sort
kan vara viktigt (i moderna skal finns det sätt att få detta, till exempel bash
”s $PIPESTATUS
array, men det här var inte alltid sant).
Kommentarer
- Jag brukar använda
sort | uniq
för 9 gånger av 10, Jag ’ jag rör faktiskt tilluniq -c
. - Observera att
sort -u
var en del av 7: e upplagan UNIX, cirka 1979. Versioner avsort
withou stöd för-u
är verkligen arkaiska – eller skrevs utan uppmärksamhet mot de facto-standarden innan POSIX ’ s de jure-standarden. Se även Stack Overflow Sortera & uniq i Linux-skal från 2010. - +1 eftersom av
ip
. Det ’ s 2016 och det här inlägget 2013, men jag vet bara omip
kommandot nu. - +1 för ” 9 gånger ut 10 I ’ jag rör faktiskt till
uniq -c
” (och kanske rör igen en gång tillsort -nr | head
). Jag undrade vad som motsvararsort | uniq
i Vim när jag fick reda på att Vim har:sort u
-kommando. Och TILsort -u
finns också. - Observera att det finns en skillnad när du använder
sort -n | uniq
vs.sort -n -u
. Till exempel kommer efterföljande och ledande vita utrymmen att ses som dubbletter avsort -n -u
men inte av den förra!echo -e 'test \n test' | sort -n -u
returnerartest
, menecho -e 'test \n test' | sort -n | uniq
returnerar båda raderna.
Svar
En skillnad är att uniq
har ett antal användbara ytterligare alternativ, till exempel hoppa över fält för jämförelse och räkna antalet repetitioner av ett värde. sort
”s -u
-flaggan implementerar endast funktionaliteten för det oskönade uniq
-kommandot. p>
Kommentarer
- +0.49 för ett användbart svar, men jag skulle uttrycka det ungefär som ” Utdata från
sort -u
kan ’ t skickas tilluniq
för att använda några av de senare ’ s användbara alternativ, som att hoppa över fält för jämförelse och räkna antalet repetitioner. ” - +1 för att kompensera naysayers eftersom ” där ’ är inget sätt att göra detta direkt från sortering ” svarar på frågan …
Svar
Med POSIX-kompatibel sort
s och uniq
s (GNU uniq
är för närvarande inte kompatibel i det avseendet), där ”är en skillnad genom att sort
använder lokalens sorteringsalgoritm för att jämföra strängar (använder vanligtvis strcoll()
för att jämföra strängar) medan uniq
söker efter bytevärdeidentitet (kommer vanligtvis att använda strcmp()
) ¹.
Det är viktigt av minst två skäl .
-
I vissa språk, särskilt på GNU-system, finns det olika tecken som sorterar lika. Till exempel, i en_US.UTF-8-platsen på ett GNU-system sorterar alla ①②③④⑤⑥⑦⑧⑨⑩ … tecken² och många andra samma eftersom deras sorteringsordning inte är definierad. De arabiska siffrorna 0123456789 sorterar samma som deras Eastern Arabic Indic motsvarigheter (٠١٢٣٤٥٦٧٨٩).
För
sort -u
, ① sorterar samma som ② och 0123 samma som ٠١٢٣ såsort -u
behåller bara en av vardera, medan föruniq
(inte GNUuniq
som använderstrcoll()
(utom med-i
)), ① är annorlunda från ② och 0123 skiljer sig från ٠١٢٣, såuniq
anser att alla 4 är unika. -
strcoll
kan bara jämföra strängar med giltiga tecken (beteendet är odefinierat enligt POSIX när ingången har sekvenser av byte som inte bildar giltiga tecken) medanstrcmp()
inte bryr sig om karaktärer eftersom det bara gör byte-till-byte-jämförelse. Så det är en annan anledning till attsort -u
kanske inte ger dig alla unika rader om vissa av dem inte utgör giltig text.sort|uniq
, medan det fortfarande är ospecificerat vid icke-textinmatning, är det i praktiken mer sannolikt att du får unika rader av den anledningen.
Förutom dessa finesser är en sak som hittills inte har noterats att uniq
jämför hela raden lexiskt, medan sort
”s -u
jämförs baserat på sorteringsspecifikationen som anges på kommandoraden.
$ 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
¹ Tidigare versioner av POSIX-specifikationen orsakade förvirring men genom att lista LC_COLLATE
variabel som en som påverkar uniq
, som togs bort i 2018-upplagan och beteendet klargjordes efter den diskussion som nämnts ovan. Se motsvarande Austin-gruppbugg
² 2019 redigera . De har sedan dess fixats, men över 95% av Unicode-kodpunkter har fortfarande en odefinierad ordning från version 2.30 av GNU libc . Du kan testa med 🧙🧚🧛🧜🧝 istället till exempel i nyare versioner
Svar
Jag föredrar att använda sort | uniq
för när jag försöker använda alternativet -u
(eliminera dubbletter) är det inte så lätt att ta bort dubbletter med blandade fallsträngar förstå resultatet.
Obs! Innan du kan köra exemplen nedan måste du simulera standard C-sorteringssekvensen genom att göra följande:
LC_ALL=C export LC_ALL
Till exempel om jag vill sortera en fil och ta bort dubbletter samtidigt som jag håller olika fall av strängar olika.
$ 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?)
Denna förvirring löses genom att inte använda alternativet -u
för att ta bort dubbletter. Att använda uniq
är mer förutsägbart. Nedan sorterar först och ignorerar fallet och skickar det sedan till uniq
för att ta bort dubbletterna.
$ sort -f short | uniq Apple apple Pear pear
Kommentarer
-
-u
alternativet försort
matar ut första av en lika körning (se man sida). Såledessort -fu
tar upp den första förekomsten av varje skiftlägeskänslig unik linje. Logiken somsort
använder för att ta bort dubbletter är förutsägbar.
Svar
En annan skillnad som jag fick reda på idag är när jag sorterar baserat på en avgränsare där sort -u
bara tillämpar den unika flaggan i kolumnen som du sorterar 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
- Detta nämns i ett svar från St é phane Chazelas men Jag gillar ditt exempel så +1
- Tack för att du påpekade @roaima, det var inte ’ t mycket tydligt i det svaret