Successivo: , Precedente: , Su: Programmi vari   [Contenuti][Indice]


11.3.6 Eliminare duplicati da un file non ordinato

Il programma uniq (vedi la sezione Stampare righe di testo non duplicate) rimuove righe duplicate da dati ordinati.

Si supponga, tuttavia, di dover rimuovere righe duplicate da un file-dati, ma di voler conservare l’ordine in cui le righe sono state scritte. Un buon esempio di questo tipo potrebbe essere un file della cronologia dei comandi della shell. Il file della cronologia dei comandi mantiene copia di tutti i comandi che sono stati dati, e non è insolito ripetere un comando molte volte di fila. Occasionalmente si potrebbe voler compattare la cronologia togliendo le righe duplicate. Tuttavia sarebbe opportuno mantenere l’ordine originale dei comandi.

Questo semplice programma fa questo. Usa due vettori. Il vettore dati ha come indice il testo di ogni riga. Per ogni riga, dati[$0] è incrementato di uno. Se una particolare riga non è stata ancora vista, dati[$0] è zero. In tal caso, il testo della riga è immagazzinato in righe[contatore]. Ogni elemento del vettore righe è un comando unico, e gli indici di righe indicano l’ordine in cui quelle righe sono state incontrate. La regola END stampa semplicemente le righe, in ordine:

# histsort.awk --- compatta un file della cronologia dei comandi della shell
# Grazie a Byron Rakitzis per l'idea generale

{
    if (dati[$0]++ == 0)
        righe[++contatore] = $0
}

END {
    for (i = 1; i <= contatore; i++)
        print righe[i]
}

Questo programma può essere un punto di partenza per generare altre informazioni utili. Per esempio, usando la seguente istruzione print nella regola END permette di sapere quante volte viene usato un certo comando:

print dati[righe[i]], righe[i]

Questo si può fare perché dati[$0] è incrementato ogni volta che una riga è stata trovata.

Rick van Rein offre il seguente programma in una riga per fare lo stesso lavoro, ossia rimuovere le righe doppie da un testo che non sia stato precedentemente ordinato alfabeticamente:

awk '{ if (! visto[$0]++) print }'

Questo programma può essere ulteriormente semplificato, con il rischio di diventare quasi indecifrabile:

awk '! visto[$0]++'

Questa versione usa l’espressione come regola da soddisfare, ed esegue l’azione di default di awk (ossia stampa la riga), quando la regola è verificata [ossia se il record non è stato ancora "visto"].


Successivo: , Precedente: , Su: Programmi vari   [Contenuti][Indice]