Successivo: , Precedente: , Su: Leggere file   [Contenuti][Indice]


4.6 Leggere campi di larghezza costante

Questa sezione tratta una funzionalità avanzata di gawk. Se si è un utente alle prime armi di awk, la si può saltare in prima lettura.

gawk fornisce una funzionalità per il trattamento di campi a larghezza fissa senza un separatore di campo distintivo. Per esempio, dati di questo tipo si trovano nell’input per vecchi programmi Fortran dove dei numeri sono elencati uno dopo l’altro, o nell’output di programmi che non prevedono che il loro output sia dato in input ad altri programmi.

Un esempio di quest’ultimo caso è una tabella dove tutte le colonne sono allineate usando un numero variabile di spazi e dove i campi vuoti sono solo spazi. Chiaramente, la normale divisione in campi di awk basata su FS non funziona bene in questa situazione. Sebbene un programma awk portabile possa usare una serie di chiamate substr() su $0 (vedi Funzioni per stringhe), questo è scomodo e inefficiente se il numero dei campi è elevato.

La suddivisione di un record in input in campi a larghezza fissa viene specificata assegnando una stringa contenente numeri separati da spazi alla variabile predefinita FIELDWIDTHS. Ogni numero specifica la larghezza del campo, comprese le colonne tra i campi. Se si vogliono ignorare le colonne tra i campi si può specificare la loro larghezza come un campo separato che verrà poi ignorato. È un errore fatale definire una larghezza di campo che abbia un valore negativo. I dati seguenti costituiscono l’output del programma di utilità Unix w. È utile per spiegare l’uso di FIELDWIDTHS:

 10:06pm  up 21 days, 14:04,  23 users
User     tty       login  idle   JCPU   PCPU  what
hzuo     ttyV0     8:58pm            9      5  vi p24.tex
hzang    ttyV3     6:37pm    50                -csh
eklye    ttyV5     9:53pm            7      1  em thes.tex
dportein ttyV6     8:17pm  1:47                -csh
gierd    ttyD3    10:00pm     1                elm
dave     ttyD4     9:47pm            4      4  w
brent    ttyp0    26Jun91  4:46  26:46   4:41  bash
dave     ttyq4    26Jun9115days     46     46  wnewmail

Il seguente programma prende l’input sopra mostrato, converte il tempo di inattività in numero di secondi, e stampa i primi due campi e il tempo di inattività calcolato:

BEGIN  { FIELDWIDTHS = "9 6 10 6 7 7 35" }
NR > 2 {
    inat = $4
    sub(/^ +/, "", inat)   # togli spazi prima del valore
    if (inat == "")
        inat = 0
    if (inat ~ /:/) {
        split(inat, t, ":")
        inat = t[1] * 60 + t[2]
    }
    if (inat ~ /days/)
        inat *= 24 * 60 * 60

    print $1, $2, inat
}

NOTA: Questo programma usa diverse funzionalità di awk non ancora trattate.

L’esecuzione del programma sui dati produce il seguente risultato:

hzuo      ttyV0  0
hzang     ttyV3  50
eklye     ttyV5  0
dportein  ttyV6  107
gierd     ttyD3  1
dave      ttyD4  0
brent     ttyp0  286
dave      ttyq4  1296000

Un altro esempio (forse più pratico) di dati di input con larghezza costante è l’input da un mazzo di schede elettorali. In alcune parti degli Stati Uniti, i votanti marcano le loro scelte perforando delle schede elettroniche.

Queste schede vengono poi elaborate per contare i voti espressi per ogni singolo candidato o su ogni determinato quesito. Siccome un votante può scegliere di non votare su alcune questioni, qualsiasi colonna della scheda può essere vuota. Un programma awk per elaborare tali dati potrebbe usare la funzionalità FIELDWIDTHS per semplificare la lettura dei dati. (Naturalmente, riuscire a eseguire gawk su un sistema con lettori di schede è un’altra storia!)

L’assegnazione di un valore a FS fa sì che gawk usi FS per separare nuovamente i campi. Si può usare ‘FS = FS’ per ottenere questo effetto, senza dover conoscere il valore corrente di FS. Per vedere quale tipo di separazione sia in atto, si può usare PROCINFO["FS"] (vedi Variabili auto-assegnate). Il suo valore è "FS" se si usa la normale separazione in campi, o "FIELDWIDTHS" se si usa la separazione in campi a larghezza fissa:

if (PROCINFO["FS"] == "FS")
    separazione in campi normale…
else if  (PROCINFO["FS"] == "FIELDWIDTHS")
    separazione in campi a larghezza fissa…
else
    separazione dei campi in base al contenuto(si veda
la sezione successiva)

Quest’informazione è utile quando si scrive una funzione che necessita di cambiare temporaneamente FS o FIELDWIDTHS, leggere alcuni record, e poi ripristinare le impostazioni originali (vedi Funzioni Passwd, per un esempio di tale funzione).


Successivo: , Precedente: , Su: Leggere file   [Contenuti][Indice]