domenica 30 dicembre 2012

Un po' di AWK. Quindicesima parte

Salve!

Ora che conosciamo la differenza tra NR e FNR (l'abbiamo vista qui), possiamo procedere con qualche esempio.

Immaginiamo di avere due file di testo. Nel primo è presente una lista dei film di Totò che abbiamo nella nostra videoteca personale e, nel secondo, i film di Totò che abbiamo già visto. Bene.


Ora chiederemo ad awk di eliminare dalla prima lista tutti i film che abbiamo già visto basandosi, per questa operazione, sulla seconda lista. Insomma, daremo in pasto ad awk entrambi i file e faremo in modo che elimini delle righe dal primo file sulla base di ciò che è scritto nel secondo file. E, dato che oggi è l'antivigilia della vigilia di capodanno, il post sarà più breve del solito. Anche se il motivo della brevità è un altro. In realtà mio nonno e Ciro hanno iniziato a suonare la fisarmonica alle 5 di mattina e io ho già il mal di testa. Si, mio nonno vuole fare la rivoluzione a suon di musica. E Ciro, che è un intellettuale di sinistra, lo accompagna con la chitarra. :( Avrei voluto oppormi al duo, ma Ciro, che è una persona intelligente e anche pastore di pecore, mi ha portato la ricotta fresca.. e allora mi sono stato zitto. Scusatemi per lo sfogo.

Andiamo a noi. Presentiamo i due file di testo.

La lista dei film di Totò che conservo nella mia videoteca (tab1.txt)
1-La banda degli onesti (1956)
2-Totò lascia o raddoppia? (1956)
3-Totò Peppino e...la malafemmina (1956)
4-Totò,Peppino e i fuorilegge (1956)
5-Totò, Vittorio e la dottoressa (1957)
6-La legge è legge (1958)
7-Totò e Marcellino (1958)
8-Totò, Peppino e le fanatiche (1958)
9-Gambe d'oro (1958)
10-I soliti ignoti (1958)
11-Totò nella luna (1958)
12-Totò a Parigi (1958)
13-Totò,Eva e il pennello proibito (1959)
Solo i numeri corrispondenti ai film che vogliamo eliminare dal primo file (tab2.txt)
4-
7-
8-
1-
2-
Lo script. (es.awk)
#!/usr/bin/awk -f

BEGIN {
       print "\n"
       FS="-"
}

{
  if(NR==FNR){
        array[$1];
   }
  else if(!($1 in array)) {
         print
 }
}
END {
     print "\n"
}
Risultato.
Ma come funziona lo script?

Ma è di una semplicità che fa paura. In pratica awk si lascia prendere un po' per i fondelli! Ehi, senza mancare di rispetto ai signori A.,W. e K.!! A loro, onore e gloria. Sempre.

 if(NR==FNR) {array[$1]}

Caro awk, quando NR e FNR sono uguali crea un array il cui indice sia il campo $1. Ma quando NR e FNR sono uguali? Ma sono uguali solo nel primo file processato!!! Andatevi a vedere il post "Un po' di AWK. Quattordicesima parte". Questo significa che l'array conterrà come indice, nel nostro esempio, solo la prima colonna del file tab2.txt, cioè i numeri 4,7,8,1 e 2.

Passiamo all'altra parte cruciale dello script.

 else if(!($1 in array)) {print}
Quando poi NR e FNR non sono più uguali (si passa così al secondo file processato), chiediamo ad awk di stampare solo quelle righe che non corrispondono ai numeri 4,7,8,1 e 2. Ed ecco svelato il mistero. Volete la prova del nove? Provate a togliere dalla riga di codice di cui sopra il punto esclamativo (!).In questo modo:

 else if(($1 in array)) {print}

Si, togliendo il punto esclamativo, il ragionamento di awk cambia. E sarà più o meno questo: Stamperò solo ed esclusivamente le righe che corrispondono agli indice dell'array. Proprio quelle righe che ho eliminato precedentemente.

Vedete?
Vero, esisterebbe anche una riga di comando compatta di awk, che fa lo stesso lavoro. Ve la presento, anche se è molto conosciuta:

 awk -F"-" 'NR==FNR{a[$1]=$1;next}!($1 in a)' tab2.txt tab1.txt

Ma così però si uccide tutta la poesia... :( E poi si continua a fare le cose meccanicamente, senza capirci un cavolo.... Alla luce di quello che abbiamo detto sopra però, si capisce pure 'sta riga. :)


Vi ricordo che l'indice del sequel "Un po' di AWK", lo trovate qui. Vi conviene dare un'occhiata anche all'indice di "Brevi Esercizi".

Non mi resta che augurarvi un buon anno!!!!

E intanto io, Lightuono e Juhan coviamo (un po' come fanno le galline). Nel nuovo anno faremo scintille!!! :D

Nessun commento:

Posta un commento