Successivo: Programma labels, Precedente: Programma alarm, Su: Programmi vari [Contenuti][Indice]
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:
daUna lista di caratteri da cui traslitterare
aUna lista di caratteri a cui traslitterare
stringaLa 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).
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: Programma labels, Precedente: Programma alarm, Su: Programmi vari [Contenuti][Indice]