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


4.9 Record su righe multiple

In alcune banche-dati, una sola riga non può contenere in modo adeguato tutte le informazioni di una voce. In questi casi si possono usare record multiriga. Il primo passo è quello di scegliere il formato dei dati.

Una tecnica è quella di usare un carattere o una stringa non usuali per separare i record. Per esempio, si può usare il carattere di interruzione di pagina (scritto ‘\f’ sia in awk che in C) per separarli, rendendo ogni record una pagina del file. Per far ciò, basta impostare la variabile RS a "\f" (una stringa contenente il carattere di interruzione di pagina). Si potrebbe ugualmente usare qualsiasi altro carattere, sempre che non faccia parte dei dati di un record.

Un’altra tecnica è quella di usare righe vuote per separare i record. Per una particolare convenzione, una stringa nulla come valore di RS indica che i record sono separati da una o più righe vuote. Quando RS è impostato alla stringa nulla, ogni record termina sempre alla prima riga vuota che è stata trovata. Il record successivo non inizia prima della successiva riga non vuota. Indipendentemente dal numero di righe vuote presenti in successione, esse costituiscono sempre un unico separatore di record. (Le righe vuote devono essere completamente vuote; righe che contengono spazi bianchi non sono righe vuote.)

Si può ottenere lo stesso effetto di ‘RS = ""’ assegnando la stringa "\n\n+" a RS. Quest’espressione regolare individua il ritorno a capo alla fine del record e una o più righe vuote dopo il record. In aggiunta, un’espressione regolare individua sempre la sequenza più lunga possibile quando una tale stringa sia presente. (vedi la sezione Quanto è lungo il testo individuato?). Quindi, il record successivo non inizia prima della successiva riga non vuota; indipendentemente dal numero di righe vuote presenti in una voce di banca-dati, esse sono considerate come un unico separatore di record.

Comunque, c’è una sostanziale differenza tra ‘RS = ""’ e ‘RS = "\n\n+"’. Nel primo caso, i ritorni a capo iniziali nel file-dati di input vengono ignorati, e se un file termina senza righe vuote aggiuntive dopo l’ultimo record, il ritorno a capo viene rimosso dal record. Nel secondo caso, questa particolare elaborazione non viene fatta. (a.b.)

Ora che l’input è separato in record, il secondo passo è quello di separare i campi all’interno dei record. Un modo per farlo è quello di dividere in campi ognuna delle righe in input nel modo solito. Questo viene fatto per default tramite una speciale funzionalità. Quando RS è impostato alla stringa nulla e FS è impostato a un solo carattere, il carattere di ritorno a capo agisce sempre come separatore di campo. Questo in aggiunta a tutte le separazioni di campo che risultano da FS.

NOTA: Quando FS è la stringa nulla (""), o un’espressione regolare, questa particolare funzionalità di RS non viene applicata; si applica al separatore di campo di default, che è costituito da un solo spazio: ‘FS = " "’.

Si noti che la formulazione della specifica POSIX implica che questa particolare funzionalità dovrebbe valere anche quando FS sia un’espressione regolare. Tuttavia, Unix awk non si è mai comportato in questo modo, e neppure gawk. Questo è fondamentalmente un errore nella specifica POSIX.

La motivazione originale per questa particolare eccezione probabilmente era quella di prevedere un comportamento che fosse utile nel caso di default (cioè, FS uguale a " "). Questa funzionalità può costituire un problema se non si vuole che il carattere di ritorno a capo faccia da separatore tra i campi, perché non c’è alcun modo per impedirlo. Tuttavia, si può aggirare il problema usando la funzione split() per spezzare i record manualmente. (vedi la sezione Funzioni di manipolazione di stringhe). Se si ha un separatore di campo costituito da un solo carattere, si può aggirare la funzionalità speciale in modo diverso, trasformando FS in un’espressione regolare contenente quel carattere singolo. Per esempio, se il separatore di campo è un carattere di percentuale, al posto di ‘FS = "%"’, si può usare ‘FS = "[%]"’.

Un altro modo per separare i campi è quello di mettere ciascun campo su una riga separata: per far questo basta impostare la variabile FS alla stringa "\n". (Questo separatore di un solo carattere individua un singolo ritorno a capo.) Un esempio pratico di un file-dati organizzato in questo modo potrebbe essere un elenco di indirizzi, in cui delle righe vuote fungono da separatore fra record. Si consideri un elenco di indirizzi in un file chiamato indirizzi, simile a questo:

Jane Doe
123 Main Street
Anywhere, SE 12345-6789

John Smith
456 Tree-lined Avenue
Smallville, MW 98765-4321
…

Un semplice programma per elaborare questo file è il seguente:

# addrs.awk --- semplice programma per una lista di indirizzi postali

# I record sono separati da righe bianche
# Ogni riga è un campo.
BEGIN { RS = "" ; FS = "\n" }

{
      print "Il nome è:", $1
      print "L'indirizzo è:", $2
      print "Città e Stato sono:", $3
      print ""
}

L’esecuzione del programma produce questo output:

$ awk -f addrs.awk addresses
-| Il nome è: Jane Doe
-| L'indirizzo è: 123 Main Street
-| Città e Stato sono: Anywhere, SE 12345-6789
-|
-| Il nome è: John Smith
-| L'indirizzo è: 456 Tree-lined Avenue
-| Città e Stato sono: Smallville, MW 98765-4321
-|
…

Vedi la sezione Stampare etichette per lettere, per un programma più realistico per gestire elenchi di indirizzi. Il seguente elenco riassume come sono divisi i record, a seconda del valore assunto da RS:

RS == "\n"

I record sono separati dal carattere di ritorno a capo (‘\n’). In effetti, ogni riga nel file-dati è un record separato, comprese le righe vuote. Questo è il comportamento di default.

RS == qualsiasi carattere singolo

I record sono separati da ogni ricorrenza del carattere specificato. Più ricorrenze adiacenti delimitano record vuoti.

RS == ""

I record sono separati da una o più righe vuote. Quando FS è un carattere singolo, il carattere di ritorno a capo serve sempre come separatore di campo, in aggiunta a qualunque valore possa avere FS. I ritorni a capo all’inizio e alla fine del file sono ignorati.

RS == regexp

I record sono separati da ricorrenze di caratteri corrispondenti a regexp. Le corrispondenze iniziali e finali di regexp designano record vuoti. (Questa è un’estensione di gawk; non è specificata dallo standard POSIX.)

Se non è eseguito in modalità di compatibilità (vedi la sezione Opzioni sulla riga di comando), gawk imposta RT al testo di input corrispondente al valore specificato da RS. Ma se al termine del file in input non è stato trovato un testo che corrisponde a RS, gawk imposta RT alla stringa nulla.


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