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


11.3.3 Rimpiazzare o eliminare caratteri

Il programma di utilità di sistema tr rimpiazza caratteri. Per esempio, è spesso usato per trasformare lettere maiuscole in lettere minuscole in vista di ulteriori elaborazioni:

generare dei dati | tr 'A-Z' 'a-z' | elaborare dei dati

tr richiede due liste di caratteri.83 Quando si elabora l’input, il primo carattere della prima lista è rimpiazzato con il primo carattere della seconda lista, il secondo carattere della prima lista è rimpiazzato con il secondo carattere della seconda lista, e così via. Se ci sono più caratteri nella lista “da” che in quella “a”, l’ultimo carattere della lista “a” è usato per i restanti caratteri della lista “da”.

In un lontano passato, un utente propose di aggiungere una funzione di traslitterazione a gawk. Il programma seguente è stato scritto per dimostrare che la traslitterazione di caratteri poteva essere fatta con una funzione definita dall’utente. Questo programma non è così completo come il programma di utilità di sistema tr, ma svolge buona parte dello stesso lavoro.

Il programma translate è stato scritto molto prima che gawk fosse in grado di separare ciascun carattere di una stringa in elementi distinti di un vettore. Questo è il motivo per cui usa ripetutamente le funzioni predefinite substr(), index(), e gsub() (vedi la sezione Funzioni di manipolazione di stringhe). Ci sono due funzioni. La prima, traduci_stringa(), richiede tre argomenti:

da

Una lista di caratteri da cui traslitterare

a

Una lista di caratteri a cui traslitterare

stringa

La stringa su cui effettuare la traslitterazione

I vettori associativi facilitano molto la parte di traslitterazione. vettore_trad contiene i caratteri “a”, indicizzato dai caratteri “da”. Poi un semplice ciclo scandisce da, un carattere alla volta. Per ogni carattere in da, se il carattere compare in stringa è rimpiazzato con il corrispondente carattere a.

La funzione traducilo() chiama traduci_stringa(), usando $0 come stringa. Il programma principale imposta due variabili globali, DA e A, dalla riga di comando, e poi modifica ARGV in modo che awk legga dallo standard input.

Infine, la regola di elaborazione si limita a chiamare traducilo() per ogni record:

# translate.awk --- fa cose simili al comando tr
# Bug: non gestisce cose del tipo tr A-Z a-z; deve essere
# descritto carattere per carattere.
# Tuttavia, se `a' è più corto di `da',
# l'ultimo carattere in `a' è usato per il resto di `da'.

function traduci_stringa(da, a, stringa,     lf, lt, lstringa, vettore_trad,
                        i, c, risultato)
{
    lf = length(da)
    lt = length(a)
    lstringa = length(stringa)
    for (i = 1; i <= lt; i++)
        vettore_trad[substr(da, i, 1)] = substr(a, i, 1)
    if (lt < lf)
        for (; i <= lf; i++)
            vettore_trad[substr(da, i, 1)] = substr(a, lt, 1)
    for (i = 1; i <= lstringa; i++) {
        c = substr(stringa, i, 1)
        if (c in vettore_trad)
            c = vettore_trad[c]
        risultato = risultato c
    }
    return risultato
}

function traducilo(da, a)
{
    return $0 = traduci_stringa(da, a, $0)
}

# programma principale
BEGIN {
    if (ARGC < 3) {
        print "sintassi: translate da a" > "/dev/stderr"
        exit
    }
    DA = ARGV[1]
    A = ARGV[2]
    ARGC = 2
    ARGV[1] = "-"
}

{
    traducilo(DA, A)
    print
}

È possibile effettuare la traslitterazione di caratteri in una funzione a livello utente, ma non è detto che sia efficiente, e noi (sviluppatori di gawk) abbiamo iniziato a prendere in considerazione l’aggiunta di una funzione. Tuttavia, poco dopo aver scritto questo programma, abbiamo saputo che Brian Kernighan aveva aggiunto le funzioni toupper() e tolower() alla sua versione di awk (vedi la sezione Funzioni di manipolazione di stringhe). Queste funzioni gestiscono la maggior parte dei casi in cui serva la traslitterazione di caratteri, e quindi abbiamo deciso di limitarci ad aggiungere le stesse funzioni a gawk, e di disinteressarci del resto.

Un miglioramento ovvio a questo programma sarebbe di impostare il vettore vettore_trad solo una volta, in una regola BEGIN. Tuttavia, ciò presuppone che le liste “da” e “a” non cambino mai durante tutta l’esecuzione del programma.

Un altro miglioramento ovvio è di consentire l’uso di intervalli, come ‘a-z’, come consentito dal programma di utilità tr. Si può trarre ispirazione dal codice di cut.awk (vedi la sezione Ritagliare campi e colonne).


Note a piè di pagina

(83)

Su alcuni sistemi più datati, incluso Solaris, la versione di sistema di tr può richiedere che le liste siano scritte come espressioni di intervallo, racchiuse in parentesi quadre (‘[a-z]’) e tra apici, per evitare che la shell effettui espansioni di nome-file. Questo non è un miglioramento.


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