Comando uniq in Linux: eliminare e contare le righe duplicate adiacenti

uniq riunisce le righe identiche consecutive in una sola riga oppure ne mostra il numero di occorrenze. Confronta soltanto gruppi adiacenti: due righe uguali separate da altre righe restano distinte. Per contare o eliminare le ripetizioni nell’intero file, puoi prima raggrupparle con sort, se puoi modificare l’ordine dei dati.

Prima di ordinare un registro o un elenco di eventi, decidi se l’ordine originale è significativo. sort | uniq cambia quell’ordine: non è una deduplicazione che conserva la sequenza iniziale. Il confronto può dipendere dalla locale, cioè dalle impostazioni linguistiche e regionali del processo; negli esempi usiamo LC_ALL=C per un confronto riproducibile sui dati di testo mostrati.

Sintassi di base

uniq [OPTION]... [INPUT [OUTPUT]]

Questa è una notazione: sostituisci opzioni e percorsi senza digitare le parentesi quadre. Senza INPUT, oppure con - al suo posto, il comando legge dall’ingresso standard. Senza OUTPUT, scrive sull’uscita standard, normalmente il terminale. Per salvare il risultato, scegli un file distinto e verifica che non contenga dati da conservare.

Gli esempi fanno riferimento a GNU uniq. Le opzioni disponibili possono variare fra implementazioni: consulta man uniq sul sistema in uso.

Esempi con dati pronti per la prova

Preparare i file ed eliminare i duplicati adiacenti

In una shell compatibile con Bash, esegui il blocco da una directory in cui puoi creare una sottodirectory. Se uniq-demo esiste già, il comando si ferma: scegli un nome nuovo senza cancellare dati esistenti. Il blocco crea due file dimostrativi e mostra il risultato del primo confronto.

mkdir uniq-demo && cd uniq-demo && (
  set -e
  set -o noclobber
  export LC_ALL=C
  printf 'apple\napple\nbanana\napple\n' > events.txt
  printf 'apple\nbanana\napple\ncherry\nbanana\n' > names.txt
  uniq events.txt
)

L’output contiene apple, banana e di nuovo apple, una voce per riga. Le prime due righe uguali vengono riunite; l’ultima non è adiacente al primo gruppo e rimane. events.txt conserva tutte e quattro le righe: controllalo con cat events.txt. Rimani nella directory uniq-demo per gli esempi sui file.

Contare le occorrenze nell’intero file

Ordina names.txt per riunire le righe identiche, poi usa -c. Imposta la stessa locale su entrambi i comandi della pipe, cioè il collegamento fra l’uscita del primo comando e l’ingresso del secondo:

LC_ALL=C sort names.txt | LC_ALL=C uniq -c

Il risultato indica 2 occorrenze di apple, 2 di banana e 1 di cherry, in quest’ordine. I numeri sono anteposti alle righe; gli spazi di allineamento possono variare secondo l’implementazione. Nessuno dei due comandi modifica il file di ingresso.

Mostrare soltanto i valori ripetuti

Con -d, il comando emette una sola riga per ogni gruppo che contiene almeno due occorrenze:

LC_ALL=C sort names.txt | LC_ALL=C uniq -d

Con questi dati compaiono apple e banana, una volta ciascuno. cherry non compare perché ha una sola occorrenza. Per ottenere invece soltanto cherry, usa LC_ALL=C sort names.txt | LC_ALL=C uniq -u. Il comportamento è diverso dall’elenco di tutti i valori distinti, che si ottiene con LC_ALL=C sort names.txt | LC_ALL=C uniq.

Distinguere i gruppi adiacenti dalle ripetizioni globali

La seguente prova è indipendente dai file precedenti. printf produce quattro righe; ogni sequenza \n nel suo formato indica una nuova riga.

printf 'apple\napple\nbanana\napple\n' | LC_ALL=C uniq -c

Output con GNU uniq; l’allineamento dei conteggi può cambiare con altre implementazioni:

      2 apple
      1 banana
      1 apple

L’ultimo conteggio 1 non è un errore: si riferisce a un nuovo gruppo di apple, separato da banana. Di conseguenza, anche uniq -u events.txt considera i gruppi adiacenti: lascia banana e l’ultimo apple. Non significa che quei valori compaiano una sola volta nell’intero file.

Se vuoi un’unica voce per ogni riga identica dell’intero file e puoi cambiare ordine, usa LC_ALL=C sort events.txt | LC_ALL=C uniq. Per preservare l’ordine iniziale eliminando anche duplicati lontani serve invece un metodo che ricordi i valori già incontrati; ordinare i dati prima di uniq non conserva quell’ordine.

Opzioni principali e criteri di confronto

Opzione Significato
-c Anteporre il numero di occorrenze consecutive a ogni riga emessa.
-d Mostrare una sola riga per ciascun gruppo adiacente ripetuto.
-u Mostrare soltanto i gruppi formati da una sola riga, eliminando interamente i gruppi ripetuti.
-i Ignorare le differenze fra maiuscole e minuscole nel confronto.
-f N Escludere dal confronto i primi N campi. Un campo comprende una sequenza di spazi o tabulazioni seguita da caratteri non vuoti; non è un campo CSV separato da virgole.

Per esempio, printf 'Apple\napple\nBanana\n' | LC_ALL=C uniq -i produce Apple e Banana: il confronto ignora il caso, ma la riga conservata non viene convertita in minuscolo. Con printf '01 apple\n02 apple\n03 banana\n' | LC_ALL=C uniq -f 1, i primi campi sono esclusi dal confronto e rimangono 01 apple e 03 banana.

Precauzioni su ordine, locale e salvataggio

Le opzioni che ignorano una parte della riga modificano il significato di «uguale». Due righe con identificatori diversi possono quindi appartenere allo stesso gruppo se usi -f. Se vuoi raggruppare righe in tutto il file in base a un confronto particolare, anche l’ordinamento precedente deve essere coerente con quel criterio: un semplice ordinamento delle righe complete non garantisce di avvicinare tutte le chiavi ignorando campi o differenze di caso.

Per una pipeline riproducibile come quelle mostrate, applica LC_ALL=C a entrambi i processi. Scrivere la variabile soltanto davanti a sort non la imposta automaticamente per uniq. Una locale diversa può cambiare confronto e gestione delle maiuscole; verifica l’effetto sui dati reali, soprattutto con testo non ASCII.

Per conservare i risultati, nella directory di prova puoi usare LC_ALL=C uniq events.txt events-unique.txt scegliendo una destinazione nuova. uniq non offre l’opzione -o di sort per riscrivere il proprio ingresso. Non usare lo stesso percorso come ingresso e uscita e non eseguire uniq events.txt > events.txt: la ridirezione può svuotare il file prima della lettura. Conserva un backup dei dati importanti e controlla il file prodotto prima di sostituire l’originale.

Domande frequenti

Perché uniq lascia righe uguali che non sono consecutive?

Il comando riconosce soltanto le ripetizioni all’interno di un gruppo adiacente. Per riunire righe identiche in tutto il file, puoi ordinarle e poi applicare uniq, se l’ordine originale non deve essere conservato.

Documentazione di riferimento

La pagina di manuale di GNU uniq su man7 descrive opzioni e gruppi adiacenti. Il riferimento POSIX per uniq specifica il comportamento standard e i vincoli su ingresso e uscita.