Successivo: Continuazione dopo errori, Precedente: File speciali, Su: Stampare [Contenuti][Indice]
Se lo stesso nome-file o lo stesso comando di shell è usato con getline
più di una volta durante l’esecuzione di un programma awk
(vedi la sezione Richiedere input usando getline
),
il file viene aperto (o il comando viene eseguito) solo la prima volta.
A quel punto, il primo record in input è letto da quel file o comando.
La prossima volta che lo stesso file o comando è usato con getline
,
un altro record è letto da esso, e così via.
Analogamente, quando un file o una pipe sono aperti in output,
awk
ricorda
il nome-file o comando a essi associato, e le successive
scritture verso lo stesso file o comando sono accodate alle precedenti
scritture.
Il file o la pipe rimangono aperti fino al termine dell’esecuzione
di awk
.
Questo implica che sono necessari dei passi speciali per rileggere nuovamente
lo stesso file dall’inizio, o per eseguire di nuovo un comando di shell
(invece che leggere ulteriore output dal precedente comando). La funzione
close()
rende possibile fare queste cose:
close(NOME_FILE)
o:
close(comando)
l’argomento NOME_FILE o comando può essere qualsiasi espressione, il cui valore dev’essere esattamente uguale alla stringa usata per aprire il file o eseguire il comando (spazi e altri caratteri “irrilevanti” inclusi). Per esempio, se si apre una pipe così:
"sort -r nomi" | getline pippo
essa va chiusa in questo modo:
close("sort -r nomi")
Una volta eseguita questa chiamata di funzione, la successiva getline
da quel file o comando, o la successiva print
o printf
verso quel
file o comando, riaprono il file o eseguono nuovamente il comando.
Poiché l’espressione da usare per chiudere un file o una pipeline deve
essere uguale all’espressione usata per aprire il file o eseguire il comando,
è buona norma usare una variabile che contenga il nome-file o il comando.
Il precedente esempio cambia come segue:
sortcom = "sort -r nomi" sortcom | getline pippo
… close(sortcom)
Questo aiuta a evitare nei programmi awk
errori di battitura
difficili da scoprire. Queste sono alcune delle ragioni per cui è bene
chiudere un file di output:
awk
. Occorre chiudere il file dopo aver finito di scriverlo, e poi
iniziare a rileggerlo con getline
.
awk
. Se i file non vengono chiusi, prima o poi awk
può
superare il limite di sistema per il numero di file aperti in un processo.
È meglio chiudere ogni file quando il programma ha finito di scriverlo.
mail
, il messaggio non è effettivamente inviato finché la pipe
non viene chiusa.
Per esempio, si supponga che una programma invii tramite una pipe
dell’output al programma mail
.
Se invia parecchie linee ridirigendole a questa pipe senza chiuderla,
queste costituiscono un solo messaggio di parecchie righe. Invece, se il
programma chiude la pipe dopo ogni riga dell’output, allora ogni riga
costituisce un messaggio separato.
Se si usano file in numero superiore a quelli che il sistema permette
di mantenere aperti,
gawk
tenta di riutilizzare i file aperti disponibili fra
i file-dati. La possibilità che gawk
lo faccia dipende dalle
funzionalità del sistema operativo, e quindi non è detto che questo riesca
sempre. È quindi sia una buona pratica
che un buon suggerimento per la portabilità quello di usare sempre
close()
sui file, una volta che si è finito di operare su di essi.
In effetti, se si usano molte pipe, è fondamentale che i comandi
vengano chiusi, una volta finita la loro elaborazione. Per esempio, si
consideri qualcosa del tipo:
{ … comando = ("grep " $1 " /qualche/file | un_mio_programma -q " $3) while ((comando | getline) > 0) { elabora output di comando } # qui serve close(comando) }
Questo esempio crea una nuova pipeline a seconda dei dati contenuti in
ogni record.
Senza la chiamata a close()
indicata come commento, awk
genera processi-figlio per eseguire i comandi, fino a che non finisce per
esaurire i descrittori di file
necessari per creare ulteriori pipeline.
Sebbene ogni comando sia stato completato (come si deduce dal codice di
fine-file restituito dalla getline
), il processo-figlio non è
terminato;28
inoltre, e questo è ciò che più ci interessa, il descrittore di file
per la pipe non è chiuso e liberato finché non si chiama
close()
o finché il programma awk
non termina.
close()
non fa nulla (e non emette messaggi) se le viene fornito come
argomento una stringa che non rappresenta un file, una pipe o un
coprocesso che sia stato aperto mediante una ridirezione. In quel caso,
close()
restituisce un codice di ritorno negativo, che indica un
errore. Inoltre, gawk
imposta ERRNO
a una stringa che indica il tipo di errore.
Si noti anche che ‘close(NOME_FILE)’ non ha effetti “magici” sul ciclo
implicito che legge ogni record dei file indicati nella riga di comando.
Si tratta, con ogni probabilità, della chiusura di un file che non era mai
stato aperto con una ridirezione,
e per questo awk
silenziosamente non fa nulla, tranne impostare un
codice di ritorno negativo.
Quando si usa l’operatore ‘|&’ per comunicare con un coprocesso,
è talora utile essere in grado di chiudere un lato della pipe
bidirezionale, senza chiudere l’altro lato.
Questo è possibile fornendo un secondo argomento a close()
.
Come in ogni altra invocazione di close()
,
il primo argomento è il nome del comando o file speciale usato
per iniziare il coprocesso.
Il secondo argomento dovrebbe essere una stringa, con uno dei due valori
"to"
[a] oppure "from"
[da]. Maiuscolo/minuscolo non fa
differenza. Poiché questa è una funzionalità avanzata, la trattazione è
rinviata alla
Comunicazioni bidirezionali con un altro processo,
che ne parla più dettagliatamente e fornisce un esempio.
Usare il codice di ritorno di
close()
In molte versioni di Unix comando = "…" comando | getline info retval = close(comando) # errore di sintassi in parecchi Unix awk
In
Lo standard POSIX è molto generico; dice che |
La terminologia tecnica è piuttosto macabra. Il processo-figlio terminato è chiamato “zombie,” e la pulizia alla fine dello stesso è chiamata “reaping” [mietitura].
Prima
della versione 4.2, il codice di ritorno dopo la chiusura di
una pipe o di un coprocesso era una cifra di due byte (16-bit),
contenente il valore restituito dalla chiamata di sistema wait()
Successivo: Continuazione dopo errori, Precedente: File speciali, Su: Stampare [Contenuti][Indice]