Successivo: Getline, Precedente: Controllare la creazione di campi, Su: Leggere file [Contenuti][Indice]
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à diRS
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, Unixawk
non si è mai comportato in questo modo, e neppuregawk
. 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: Getline, Precedente: Controllare la creazione di campi, Su: Leggere file [Contenuti][Indice]