mercoledì 24 ottobre 2012

Un po' di AWK. Nona parte.

Se l'altra volta abbiamo parlato di campi (qui), oggi ci tocca parlare di records!

Partiamo dal seguente testo:

Luigi, 39 anni; Ciro, 61 anni; Mio nonno, 82 anni;

Come potete vedere, è una singola linea di testo. Potremmo dire che è un singolo record!
Usare il condizionale è d'obbligo; infatti sta a noi, in un certo senso, stabilire il
numero dei records, cioè il numero di righe in cui dividere questa nostra unica linea.

E come lo possiamo fare?

Mediante la variabile RS.
RS è una variabile Built-in di AWK, cioè una variabile il cui valore è predefinito.
E qual è questo valore? E' una nuova linea "\n"

Infatti se imposto la seguente riga di comando,

echo "Luigi,39 anni; Ciro,61 anni; Mio nonno,82 anni;"| awk '{print $0}'

il risultato sarà l'intera linea di testo, appunto perchè il valore predefinito della variabile RS è "\n".

Ma se al posto di "\n" mettiamo, ad esempio, il punto e virgola, capirete che le cose cambiano di brutto!

Infatti,

echo "Luigi, 39 anni;Ciro, 61 anni;Nonno, 82 anni;"| awk 'BEGIN {RS=";"} {print $0}'

Risultato:

Luigi,39 anni
Ciro,61 anni
Nonno,82 anni


Detto meglio, RS è la variabile che permette ad AWK di formattare i records in entrata. Ma se c'è un'entrata, ci deve essere anche un'uscita. Non sempre! Io per colpa del nonno e di Ciro, che ho debitamente citato entrambi nell'esempio di cui sopra, sono entrato nel tunnel di AWK e non riesco più ad uscirne. Vabbè, la mia sarà un'eccezione; e le eccezioni confermano le regole, almeno così, ricordo, diceva il mio vecchio professore di matematica che è morto, poverino, investito da un treno. Sarà stata un'eccezione?

L'uscita di cui parlavamo introduce l'altra variabile, ORS.

ORS è la variabile preposta alla formattazione del testo in uscita. Ha un valore predefinito che, come per RS, è la nuova linea "\n" Gli autori di questo strepitoso linguaggio tuonano così: "Output Record Separator, a newline by default." Mica noccioline!

Prendiamo la nostra solita riga di testo

Luigi, 39 anni;Ciro, 61 anni;Mio nonno, 82 anni;

e facciamo un esperimento.

Cambiamo "\n" con "\n ----- \n" e vediamo cosa ne viene fuori.


echo "Luigi, 39 anni;Ciro, 61 anni;Nonno, 82 anni;"| awk 'BEGIN {RS=";";ORS="\n----\n"} {print $0}'

Eccone il risultato:

Luigi, 39 anni
----
Ciro, 61 anni
----
Nonno, 82 anni
----


È più chic, vero?

E ora passiamo a NR. Faccio parlare ancora una volta gli autori di questo linguaggio. "The total Number of input Records seen so far" Quasi quasi mi commuovo...Essì, NR sta per Numero di Records e via dicendo...

Ritorniamo alla nostra linea di testo.

Luigi, 39 anni;Ciro, 61 anni;Mio nonno, 82 anni;

Se il valore di RS non viene cambiato, quindi resta la nuova linea, ecco cosa succede:

echo "Luigi, 39 anni;Ciro, 61 anni;Nonno, 82 anni;"| awk 'END {print NR}'


Succede che avremo un solo record.

Ma se ad RS gli assegnamo come valore ";", avremo che...

echo "Luigi, 39 anni;Ciro, 61 anni;Nonno, 82 anni"| awk 'BEGIN{RS=";"} END{print NR}'

...avremo che i records saranno tre!!! E non è poco...

NR è di un'utilità fondamentale, ritornerà spesso nel sequel "Un po' di AWK"

Facciamo qualche altro esempio usando ancora NR.

Ad esempio, potrei chiedere ad awk di estrarre solo i records dispari!

echo "Luigi, 39 anni;Ciro, 61 anni;Nonno, 82 anni;"| awk 'BEGIN{RS=";"} (NR % 2) {print}'

In tal caso verremmo fuori io e il nonno, vedete?

Risultato:
Luigi, 39 anni
Nonno, 82 anni


Oppure potrei chiedere di estrarre soli i records pari.

echo "Luigi, 39 anni;Ciro, 61 anni;Nonno, 82 anni;"| awk 'BEGIN{RS=";"} (NR % 2)==0 {print}'

In tal caso esce solo l'amico Ciro che vi ricordo  fa il pastore come professione ed è un estimatore di AWK.

Risultato:
Ciro, 61 anni

Ok, per oggi basta così.

Alla prossima, qualora lo vogliate. Ciao.

P.S. Vi ricordo che l'indice del sequel "Un po' di AWK", lo trovate qui. Mentre qui trovate l'indice di "Mission Python" e qui l'indice del "Progetto Bash".

Nessun commento:

Posta un commento