Qual è la differenza tra “ sort -u ” e “ sort | uniq ”?

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

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 a uniq -c.
  • Tieni presente che sort -u faceva parte della settima edizione UNIX, intorno al 1979. Versioni di sort 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 comando ip.
  • +1 per ” 9 volte su 10 10 ‘ sto attualmente convogliando a uniq -c ” (e forse ancora una volta a sort -nr | head). Mi chiedevo quale fosse lequivalente di sort | uniq in Vim quando ho scoperto che Vim ha il comando :sort u. E esiste anche TIL sort -u.
  • Tieni presente che cè una differenza quando si utilizza sort -n | uniq e sort -n -u. Ad esempio, gli spazi bianchi finali e iniziali saranno visti come duplicati da sort -n -u ma non dal primo! echo -e 'test \n test' | sort -n -u restituisce test, ma echo -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 a uniq 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 ٠١٢٣ quindi sort -u manterrà solo uno di ciascuno, mentre per uniq (non GNU uniq che utilizza strcoll() (tranne con -i)), ① è diverso da ② e 0123 diverso da ٠١٢٣, quindi uniq 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) mentre strcmp() non si preoccupa sui caratteri poiché esegue solo il confronto byte-byte. Quindi “questo è un altro motivo per cui sort -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 di sort restituisce il primo di una corsa uguale (vedi pagina man). Pertanto sort -fu rileva la prima occorrenza di ogni riga unica senza distinzione tra maiuscole e minuscole. La logica utilizzata da sort 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

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *