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


4.7 Definire i campi in base al contenuto

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

Normalmente, quando si usa FS, gawk definisce i campi come le parti del record che si trovano tra due separatori di campo. In altre parole, FS definisce cosa un campo non è, invece di cosa è. Tuttavia, ci sono casi in cui effettivamente si ha bisogno di definire i campi in base a cosa essi sono, e non in base a cosa non sono.

Il caso più emblematico è quello dei dati cosiddetti comma-separated value (CSV). Molti fogli elettronici, per esempio, possono esportare i dati in file di testo, dove ogni record termina con un ritorno a capo e i campi sono separati tra loro da virgole. Se le virgole facessero solo da separatore fra i dati non ci sarebbero problemi. Il problema sorge se uno dei campi contiene una virgola al suo interno. In queste situazioni, la maggioranza dei programmi include il campo fra doppi apici.24 Così, potremmo avere dei dati di questo tipo:

Robbins,Arnold,"1234 A Pretty Street, NE",MyTown,MyState,12345-6789,USA

La variabile FPAT offre una soluzione per casi come questo. Il valore di FPAT dovrebbe essere una stringa formata da un’espressione regolare. L’espressione regolare descrive il contenuto di ciascun campo.

Nel caso dei dati CSV visti prima, ogni campo è “qualsiasi cosa che non sia una virgola,” oppure “doppi apici, seguiti da qualsiasi cosa che non siano doppi apici, e doppi apici di chiusura”. (Ci sono definizioni di dati CSV più complicate, vedere più sotto.) Se fosse scritta come una costante regexp (vedi la sezione Espressioni regolari), sarebbe /([^,]+)|("[^"]+")/. Dovendola scrivere come stringa si devono proteggere i doppi apici, e quindi si deve scrivere:

FPAT = "([^,]+)|(\"[^\"]+\")"

Come esempio pratico, si può vedere questo semplice programma che analizza e divide i dati:

BEGIN {
    FPAT = "([^,]+)|(\"[^\"]+\")"
}

{
    print "NF = ", NF
    for (i = 1; i <= NF; i++) {
        printf("$%d = <%s>\n", i, $i)
    }
}

Eseguendolo, avendo in input la riga vista sopra, si ottiene:

$ gawk -f simple-csv.awk addresses.csv
NF =  7
$1 = <Robbins>
$2 = <Arnold>
$3 = <"1234 A Pretty Street, NE">
$4 = <MyTown>
$5 = <MyState>
$6 = <12345-6789>
$7 = <USA>

Si noti la virgola contenuta nel valore del campo $3.

Un semplice miglioramento se si elaborano dati CSV di questo tipo potrebbe essere quello di rimuovere i doppi apici, se presenti, con del codice di questo tipo:

if (substr($i, 1, 1) == "\"") {
    len = length($i)
    $i = substr($i, 2, len - 2) # Ottiene il testo tra doppi apici
}

NOTA: Alcuni programmi esportano dei dati CSV che contengono dei ritorni a capo al loro interno in campi rinchiusi tra doppi apici. gawk non è in grado di trattare questi dati. Malgrado esista una specifica ufficiale per i dati CSV, non c’è molto da fare; il meccanismo di FPAT fornisce una soluzione elegante per la maggioranza dei casi, e per gli sviluppatori di gawk ciò può bastare.

Come visto, l’espressione regolare usata per FPAT richiede che ogni campo contenga almeno un carattere. Una semplice modifica (cambiare il primo ‘+’ con ‘*’) permette che siano presenti dei campi vuoti:

FPAT = "([^,]*)|(\"[^\"]+\")"

Come per FS, la variabile IGNORECASE (vedi la sezione Variabili predefinite modificabili per controllare awk) ha effetto sulla separazione dei campi con FPAT.

Se si assegna un valore a FPAT la divisione in campi non viene effettuata utilizzando FS o FIELDWIDTHS.

Infine, la funzione patsplit() rende la stessa funzionalità disponibile per suddividere normali stringhe (vedi la sezione Funzioni di manipolazione di stringhe).


Note a piè di pagina

(24)

Il formato CSV non ha avuto, per molti anni, una definizione standard formale. RFC 4180 standardizza le pratiche più comuni.


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