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


11.3.8 Un semplice editor di flusso

Il programma di utilità sed è un editore di flusso, ovvero un programma che legge un flusso di dati, lo modifica, e scrive il file così modificato. È spesso usato per fare modifiche generalizzate a un grosso file, o a un flusso di dati generato da una pipeline di comandi. Sebbene sed sia un programma piuttosto complesso di suo, l’uso che se ne fa solitamente è di effettuare delle sostituzioni globali attraverso una pipeline:

comando1 < dati.originali | sed 's/vecchio/nuovo/g' | comando2 > risultato

Qui, ‘s/vecchio/nuovo/g’ chiede a sed di ricercare la regexpvecchio’ in ogni riga di input e di sostituirla dappertutto con il testo ‘nuovo’ (cioè, in tutte le occorrenze di ciascuna riga). Questo è simile a quello che fa la funzione di awk gsub() (vedi la sezione Funzioni di manipolazione di stringhe).

Il programma seguente, awksed.awk, accetta almeno due argomenti dalla riga di comando: l’espressione da ricercare e il testo con cui rimpiazzarla. Ogni ulteriore argomento è considerato come un nome di file-dati da elaborare. Se non ne viene fornito alcuno, si usa lo standard input:

# awksed.awk --- fa s/pippo/pluto/g usando solo print
#    Ringraziamenti a Michael Brennan per l'idea

function sintassi()
{
    print "sintassi: awksed espressione rimpiazzo [file...]" > "/dev/stderr"
    exit 1
}

BEGIN {
    # valida argomenti
    if (ARGC < 3)
        sintassi()

    RS = ARGV[1]
    ORS = ARGV[2]

    # non usare argomenti come nomi di file
    ARGV[1] = ARGV[2] = ""
}

# guarda, mamma, senza mani!
{
    if (RT == "")
        printf "%s", $0
    else
        print
}

Il programma fa assegnamento sulla capacità di gawk di avere come RS una regexp, e anche sul fatto che RT viene impostato al testo che effettivamente delimita il record (vedi la sezione Controllare come i dati sono suddivisi in record).

L’idea è di usare RS come espressione da ricercare. gawk automaticamente imposta $0 al testo che compare tra due corrispondenze all’espressione di ricerca. Questo è appunto il testo che vogliamo conservare inalterato. Quindi, impostando ORS al testo che si vuole sostituire, una semplice istruzione print scrive il testo che si vuole mantenere, seguito dal testo che si vuole invece sostituire.

C’è un problema in questo schema, ossia cosa fare se l’ultimo record non termina con un testo che corrisponde a RS. Usando un’istruzione print incondizionatamente stampa il testo da sostituire, il che non è corretto. Tuttavia, se il file non termina con del testo che corrisponde a RS, RT è impostata alla stringa nulla. In tal caso, si può stampare $0 usando printf (vedi la sezione Usare l’istruzione printf per stampe sofisticate).

La regola BEGIN gestisce la preparazione, controllando che ci sia il numero giusto di argomenti e chiamando sintassi() se c’è un problema. Poi imposta RS e ORS dagli argomenti della riga di comando e imposta ARGV[1] e ARGV[2] alla stringa nulla, per impedire che vengano considerati dei nomi-file (vedi la sezione Usare ARGC e ARGV).

La funzione sintassi() stampa un messaggio di errore ed esce. Per finire, l’unica regola gestisce lo schema di stampa delineato più sopra, usando print o printf come richiesto, a seconda del valore di RT.


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