>
MENU

Creare utenti FTP senza shell e con chroot con...

winehq_top_logo.png

Wine: passare da Windows a Linux senza rinunciare a...

27 agosto 2007 Visualizzazioni: 619 Focus

Estrarre informazioni da file di testo con AWK

Capita frequentemente di dover elaborare file di testo contenenti dati da caricare in qualche database, o spedire in FTP a qualche sistema legacy. E se i file contengono centinaia di migliaia di righe, diventa difficile caricarli in qualche area di staging come database relazionali, Microsoft Excel, ecc. Inoltre, potrebbe esservi la necessità di elaborare questi file periodicamente, e quindi di arrivare ad una soluzione schedulabile automatizzata.

awk.jpg

Ad inizio carriera, questo compito era assolto da una serie di programmi C che scrivevo in brevissimo tempo e che costituivano una sorta di libreria di strumenti sempre pronti. Rimanendo comunque valida questa possibilità, si può guardare anche ad esempio alla famosa utility AWK di UNIX, che permette di fare praticamente tutto.

Un esempio abbastanza semplice è però in grado di mostrare tutte le potenzialità dello strumento: supponiamo di avere un file con centinaia di migliaia di linee, che rappresentanto l’hardware di una società; il file ha le colonne separate da un carattere di tabulazione; la colonna tipo indica se il pezzo è un computer, una stampante, un monitor o altro. Le colonne sono le seguenti:

COSTRUTTORE TIPO MATRICOLA MODELLO

Quello che si vorrebbe ottenere è un conteggio delle linee per ogni tipo, sapere cioè, quante linee sono stampanti, quanti monitore e così via. Chiaramente caricando il file di testo su un database, con una semplice GROUP BY sarebbe possibile velocemente tirare fuori l’informazione, ma la stessa informazione si può facilmente tirare fuori anche con AWK, con la linea seguente:

gawk "{ tipo[$2]++ } END { for (indice in tipo) print indice, tipo[indice]}" d:cdc.txt

Questo comando, applicato ad un file chiamato cdc.txt, composto come segue:

COSTRUTTORE TIPO, MATRICOLA, MODELLO
SIEMENS SERVER xx404540 X320
SIEMENS SERVER sdf2362362 X350
HP COMPUTER 3254320 HP845
HP STANMPANTE 32534621 HP640
EPSON STAMPANTE xl7878 C42UX
EPSON COMPUTER xc62763 EPC526

produrrebbe in uscita:

COMPUTER 2
STAMPANTE 2
SERVER 2
TIPO 1

Nel comando si è utilizzata la caratteristica degli array associativi di AWK. Il codice { tipo[$2]++ }, che viene applicato a tutto il file linea per linea, crea un array di nome tipo, il cui indice è la seconda colonna (che in AWK si indica con $2), cioè proprio il tipo di hardware del file. Questo significa che quando incontrerà un nuovo tipo, ad esempio, server, verrà creata una nuova cella nell’array tipo, che avrà indice proprio SERVER, e il valore sarà 1; si utilizza perciò l’operatore ++ che può essere tradotto per chiarezza con: tipo[$2]=tipo[$2]+1. Ogni linea che avrà come tipo SERVER, produrrà un incremento della cella tipo[SERVER].

La parte che segue END, viene eseguita alla fine della lettura di tutto il file e si occupa di stampare i risultati. Un semplice ciclo for scandisce l’array creato, e per ogni cella, stampa l’indice (il tipo) e il valore. Notare che nell’output è presente anche TIPO 1, che è il conteggio per la linea di intestazione. Questo può essere evitato utilizzando la variabile incorporata FNR, che indica il numero di record attuale nel file:

gawk "{ if (FNR!=1) tipo[$2]++ } END { for (indice in tipo) print indice, tipo[indice]}" d:cdc.txt


di Emanuele Gianturco - Programmazione.it

twittergoogle_pluslinkedinmail
  • MAXI

    i would like to much about tipo,matricola.T.E.M.A

  • MAXI

    COSTRUTTORE TIPO, MATRICOLA, MODELLO
    SIEMENS SERVER xx404540 X320
    SIEMENS SERVER sdf2362362 X350
    HP COMPUTER 3254320 HP845
    HP STANMPANTE 32534621 HP640
    EPSON STAMPANTE xl7878 C42UX
    EPSON COMPUTER xc62763 EPC526

    produrrebbe in uscita: