#howtodev - Usare AWK pt2: strutture di controllo

Scritto da il
Redatto da
bash
awk

← Articolo precedente, parte 1: Sintassi base

AWK è un linguaggio di programmazione nato dalla necessità di manipolare piccole porzioni di testo in diversi file con poche righe di codice, sfruttando direttamente l’interattività della console.

I tre autori (Aho, Weinberger, Kernighan) hanno dato vita a questo potente strumento negli anni 70, dandogli il nome in base alle loro iniziali, e migliorandolo con il tempo.

Parte 2: costrutti e for.

Variabili complesse

Prima di entrare nell’argomento principale va esteso un concetto incontrato nell’articolo precedente: le variabili.

Che tipologie di variabili supporta AWK? numeriche, stringhe ma anche array e dizionari. Come qualunque altra variabile, AWK inizializza le variabili nello stesso momento in cui le si usa, e deduce il tipo dal contesto. Un esempio molto semplice potrebbe essere contare il numero di parole in ogni frase e stamparle alla fine:

echo 'Oh, bravo Figaro!
Bravo, bravissimo! Bravo!
Fortunatissimo per verità! Bravo!
Fortunatissimo per verità,
fortunatissimo per verità!' | awk '
    {vettore[c++]=NF}
    END{
        print("Parole nella 1 frase:",vettore[0])
        print("Parole nella 2 frase:",vettore[1])
        print("Parole nella 3 frase:",vettore[2])
        print("Parole nella 4 frase:",vettore[3])
        print("Parole nella 5 frase:",vettore[4])
    }'

Nel codice viene creata ed inizializzata la variabile vettore insieme alla variabile c.
La prima serve a memorizzare, per ogni singola riga letta, il numero di parole. Tramite la variabile c viene creato un “indice” che aumenta riga per riga.

Alla fine come si può notare, si usano gli indici da 0 a 5 per mostrare tutti i vari valori.

For ed altri costrutti

I costrutti sono simili ad altri linguaggi, abbiamo quindi il while, il for, l’ if e le normalissime strutture di controllo.

Per chi viene da altri linguaggi di programmazione il passaggio è assolutamente immediato. Per chiunque non fosse invece avvezzo:

  • Il costrutto “if” determina un blocco di istruzioni che viene eseguito solo ad una determinata condizione.
  • Il costrutto “while” determina un blocco di istruzioni che viene eseguito fino a che una determinata condizione resta vera.
  • Il costrutto “for” crea una variabile, esegue un blocco di istruzioni fino a che una determinata condizione resta vera ed ogni iterazione aggiorna la variabile creata.

Un “if” ha una struttura similare a questa:

if(condizione){
    ... istruzioni ...
}

Un “while”:

while(condizione) {
    ...istruzioni...
}

Mentre un “for”, a questa:

for(inizializzazione;condizione;aggiornamento){
    ... istruzioni ...
}

IF esempi

Ad esempio per stampare il numero di righe che contengono la parola “bravo” o “Bravo”:

echo 'Oh, bravo Figaro!
Bravo, bravissimo! Bravo!
Fortunatissimo per verità! Bravo!
Fortunatissimo per verità,
fortunatissimo per verità!' | awk '
    {
        if($0~"[bB]ravo"){
                c++;
        }
    }
    END{
        print("numero di parole che contengono \"bravo\":",c);
    }'

L’output sarà:

numero di parole che contengono "bravo": 3

FOR Esempi

Si può ora, grazie al for, scendere più nel dettaglio e contare il numero di “occorrenze” di bravo:

echo 'Oh, bravo Figaro!
Bravo, bravissimo! Bravo!
Fortunatissimo per verità! Bravo!
Fortunatissimo per verità,
fortunatissimo per verità!' | awk '
    {
        for(i=1; i<=NF; i++){
                if($i~"[bB]ravo"){
                        c++;
                }
        }
    }
    END{
        print("numero di \"bravo\":",c);
    }
'

Il risultato è

numero di "bravo": 4

Split di una stringa nei vari caratteri

Un altro esempio pratico potrebbe essere lo split di una stringa nei singoli caratteri e contare le occorrenze di alcuni.
Lo split di una stringa si fa attraverso una funzione chiamata split:

split(stringa,vettorerisultante,divisore)

Ad esempio:

split($0,chars,"")

Divide l’intera riga in ingresso ad AWK dentro il vettore chars.

Un esempio completo potrebbe essere quello di contare il numero di a in un file di testo, il comando sarebbe:

echo 'Oh, bravo Figaro!
Bravo, bravissimo! Bravo!
Fortunatissimo per verità! Bravo!
Fortunatissimo per verità,
fortunatissimo per verità!' | awk '
    {
        split($0,chars,""); 
        for (i=1; i<=length($0); i++) {
            if(chars[i]=="a"){ 
                ca++;
            }
        }
    } 
    END { print ("ci sono",ca,"a");} 
'

L’output è:

ci sono 9 a
history_edu Revisioni