Ovunque vedo qualcuno che ha bisogno di ottenere un elenco ordinato e univoco, reindirizza sempre a sort | uniq
. Non ho mai visto esempi in cui qualcuno usa sort -u
. Perché no? Qual è la differenza e perché è meglio usare uniq piuttosto che il flag univoco per ordinare?
Commenti
- aplawrence.com/Unixart/sort-vs-uniq.html
Risposta
sort | uniq
esisteva prima di sort -u
ed è compatibile con una gamma più ampia di sistemi, sebbene quasi tutti i sistemi moderni supportino -u
– è POSIX. È principalmente un ritorno al passato ai giorni in cui sort -u
non esisteva “(e le persone non tendono a cambiare i loro metodi se il modo in cui sanno continua a funzionare, basta guardare ifconfig
rispetto a ip
adozione).
I due sono stati probabilmente uniti perché la rimozione di duplicati allinterno di un file richiede lordinamento (almeno, nello standard case), ed è un caso duso estremamente comune. È anche più veloce internamente perché è in grado di eseguire entrambe le operazioni contemporaneamente (e perché “non richiede IPC tra uniq
e sort
). Soprattutto se il file è grande, sort -u
probabilmente utilizzerà meno file intermedi per ordinare i dati.
Sul mio sistema Ottengo costantemente risultati come questo:
$ 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
Inoltre non “maschera il codice di ritorno di sort
, che può essere importante (nelle shell moderne ci sono modi per ottenerlo, ad esempio, bash
“s $PIPESTATUS
array, ma questo non era” t sempre vero).
Commenti
- Tendo a usare
sort | uniq
perché 9 volte su 10, ‘ in realtà sto collegando auniq -c
. - Tieni presente che
sort -u
faceva parte della settima edizione UNIX, intorno al 1979. Versioni disort
senza Il supporto per-u
è veramente arcaico o è stato scritto senza attenzione allo standard de facto prima dello standard ‘ de jure di POSIX. Vedi anche Stack Overflow Ordina & uniq nella shell Linux del 2010. - +1 perché di
ip
. È ‘ 2016 e questo post nel 2013, ma ora conosco solo il comandoip
. - +1 per ” 9 volte su 10 10 ‘ sto attualmente convogliando a
uniq -c
” (e forse ancora una volta asort -nr | head
). Mi chiedevo quale fosse lequivalente disort | uniq
in Vim quando ho scoperto che Vim ha il comando:sort u
. E esiste anche TILsort -u
. - Tieni presente che cè una differenza quando si utilizza
sort -n | uniq
esort -n -u
. Ad esempio, gli spazi bianchi finali e iniziali saranno visti come duplicati dasort -n -u
ma non dal primo!echo -e 'test \n test' | sort -n -u
restituiscetest
, maecho -e 'test \n test' | sort -n | uniq
restituisce entrambe le righe.
Risposta
Una differenza è che uniq
ha una serie di utili opzioni aggiuntive, come saltare i campi per il confronto e contare il numero di ripetizioni di un valore. Il flag sort
“s -u
implementa solo la funzionalità del comando uniq
non decorato.
Commenti
- +0,49 per una risposta utile, ma la formulerei qualcosa come ” Loutput di
sort -u
non può ‘ essere passato auniq
per utilizzare alcuni di questi ultimi ‘ opzioni utili, come saltare i campi per il confronto e contare il numero di ripetizioni. ” - +1 per compensare il oppositori perché ” non ‘ è possibile farlo direttamente dallordinamento ” risponde alla domanda …
Risposta
Con sort
e uniq
s (GNU uniq
non è attualmente conforme a tale riguardo), cè “una differenza in quanto sort
utilizza lalgoritmo di confronto delle impostazioni locali per confrontare le stringhe (in genere utilizzerà strcoll()
per confrontare le stringhe) mentre uniq
controlla lidentità del valore in byte (in genere utilizza strcmp()
) ¹.
Ciò è importante per almeno due motivi .
-
In alcune versioni locali, specialmente su sistemi GNU, ci sono caratteri diversi che ordinano lo stesso. Ad esempio, nella locale en_US.UTF-8 su un sistema GNU, tutti i caratteri ①②③④⑤⑥⑦⑧⑨⑩ …² e molti altri ordinano allo stesso modo perché il loro ordinamento non è definito. Le cifre arabe 0123456789 hanno lo stesso ordinamento delle loro controparti arabo indiano orientale (٠١٢٣٤٥٦٧٨٩).
Per
sort -u
, ① ordina come ② e 0123 come ٠١٢٣ quindisort -u
manterrà solo uno di ciascuno, mentre peruniq
(non GNUuniq
che utilizzastrcoll()
(tranne con-i
)), ① è diverso da ② e 0123 diverso da ٠١٢٣, quindiuniq
considererebbe tutti e quattro unici. -
strcoll
può confrontare solo stringhe di caratteri validi (il comportamento non è definito come per POSIX quando linput ha sequenze di byte che non formano caratteri validi) mentrestrcmp()
non si preoccupa sui caratteri poiché esegue solo il confronto byte-byte. Quindi “questo è un altro motivo per cuisort -u
potrebbe non darti tutte le righe univoche se alcune di esse non formano un testo valido.sort|uniq
, sebbene non sia ancora specificato sullinput non di testo, in pratica è più probabile che fornisca righe univoche per questo motivo.
Oltre a queste sottigliezze, una cosa che finora non è stata notata è che uniq
confronta lessicalmente lintera linea, mentre sort
“s -u
confronta in base alla specifica di ordinamento fornita sulla riga di comando.
$ 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
¹ Tuttavia, le versioni precedenti della specifica POSIX creavano confusione elencando la variabile LC_COLLATE
come una variabile che influiva su uniq
, che è stata rimossa nelledizione 2018 e il comportamento chiarito a seguito della discussione sopra menzionata. Vedi il bug del gruppo Austin corrispondente
² 2019 modifica . Da allora sono stati risolti, ma oltre il 95% dei punti di codice Unicode ha ancora un ordine indefinito a partire dalla versione 2.30 della GNU libc . Puoi provare con 🧙🧚🧛🧜🧝 invece, ad esempio, nelle versioni più recenti
Risposta
Preferisco usare sort | uniq
perché quando provo a utilizzare lopzione -u
(elimina i duplicati) per rimuovere i duplicati che coinvolgono stringhe di maiuscole e minuscole, non è così facile comprendere il risultato.
Nota: prima di poter eseguire gli esempi seguenti, è necessario simulare la sequenza di ordinamento C standard procedendo come segue:
LC_ALL=C export LC_ALL
Ad esempio, se voglio ordinare un file e rimuovere i duplicati, mantenendo allo stesso tempo distinti i diversi casi di stringhe.
$ 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?)
Questa confusione viene risolta non utilizzando lopzione -u
per rimuovere i duplicati. Lutilizzo di uniq
è più prevedibile. Quanto segue prima ordina e ignora il caso e poi lo passa a uniq
per rimuovere i duplicati.
$ sort -f short | uniq Apple apple Pear pear
Commenti
-
-u
opzione disort
restituisce il primo di una corsa uguale (vedi pagina man). Pertantosort -fu
rileva la prima occorrenza di ogni riga unica senza distinzione tra maiuscole e minuscole. La logica utilizzata dasort
per rimuovere i duplicati è prevedibile.
Risposta
Unaltra differenza che ho scoperto oggi è quando si ordina in base a un delimetro in cui sort -u
applica il flag univoco solo sulla colonna con cui si ordina.
$ 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
Commenti
- Questo è menzionato in una risposta di St é phane Chazelas ma Mi piace il tuo esempio quindi +1
- Grazie per aver segnalato @roaima, non era ‘ molto chiaro in quella risposta