Successivo: Funzioni di tempo, Precedente: Funzioni per stringhe, Su: Funzioni predefinite [Contenuti][Indice]
Le seguenti funzioni riguardano l’input/output (I/O). I parametri opzionali sono racchiusi tra parentesi quadre ([ ]):
close(nome_file [, come])Chiude il file nome_file in input o in output. Alternativamente, l’argomento può essere un comando della shell usato per creare un coprocesso, o per ridirigere verso o da una pipe; questo coprocesso o pipe viene chiuso. Vedi la sezione Chiudere ridirezioni in input e in output per ulteriori informazioni.
Quando si chiude un coprocesso, può talora essere utile chiudere dapprima
un lato della pipe bidirezionale e quindi chiudere l’altro.
Questo si può fare fornendo un secondo argomento a close().
Questo secondo argomento (come)
dovrebbe essere una delle due stringhe "to" o "from",
che indicano quale lato della pipe chiudere. La stringa può essere
scritta indifferentemente in maiuscolo o in minuscolo.
Vedi la sezione Comunicazioni bidirezionali con un altro processo,
che tratta questa funzionalità con maggior dettaglio e mostra un esempio.
Si noti che il secondo argomento di close() è
un’estensione gawk; non è disponibile in modalità compatibile
(vedi la sezione Opzioni sulla riga di comando).
fflush([nome_file])Scrive su disco ogni output contenuto in memoria, associato con nome_file, che è o un file aperto in scrittura o un comando della shell che ridirige output a una pipe o a un coprocesso.
Molti programmi di utilità bufferizzano il loro output (cioè,
accumulano in memoria record da scrivere in un file su disco o sullo
schermo, fin quando non arriva il momento giusto per inviare i
dati al dispositivo di output).
Questo è spesso più efficiente che scrivere
ogni particella di informazione non appena diventa disponibile. Tuttavia,
qualche volta è necessario forzare un programma a svuotare
i suoi buffer (cioè, inviare l’informazione alla sua destinazione,
anche se un buffer non è pieno).
Questo è lo scopo della funzione fflush(); anche
gawk scrive il suo output in un buffer, e la funzione fflush()
forza gawk a svuotare i suoi buffer.
Brian Kernighan ha aggiunto fflush() al suo awk nell’aprile
1992. Per due decenni è rimasta un’estensione comune. A Dicembre
2012 è stata accettata e inclusa nello standard POSIX.
Si veda il sito Web dell’Austin Group.
POSIX standardizza fflush() come segue: se non c’è alcun
argomento, o se l’argomento è la stringa nulla (""),
awk svuota i buffer di tutti i file in output e di
tutte le pipe.
NOTA: Prima della versione 4.0.2,
gawkavrebbe svuotato solo i buffer dello standard output se non era specificato alcun argomento, e svuotato tutti i buffer dei file in output e delle pipe se l’argomento era la stringa nulla. Questo è stato modificato per essere compatibile con l’awkdi Kernighan, nella speranza che standardizzare questa funzionalità in POSIX sarebbe stato più agevole (come poi è effettivamente successo).Con
gawk, si può usare ‘fflush("/dev/stdout")’ se si desidera solo svuotare i buffer dello standard output.
fflush() restituisce zero se il buffer è svuotato con successo;
altrimenti, restituisce un valore diverso da zero. (gawk
restituisce -1.)
Nel caso in cui tutti i buffer vadano svuotati, il valore restituito è zero
solo se tutti i buffer sono stati svuotati con successo. Altrimenti,
è -1, e gawk avvisa riguardo al nome_file
che ha problemi.
gawk invia anche un messaggio di avvertimento se si tenta di svuotare i
buffer di un file o pipe che era stato aperto in lettura
(p.es. con getline),
o se nome_file non è un file, una pipe, o un coprocesso aperto.
in tal caso, fflush() restituisce ancora -1.
|
Bufferizzazione interattiva e non interattiva
A complicare ulteriormente le cose, i problemi di bufferizzazione possono peggiorare se il programma eseguito è interattivo (cioè, se comunica con un utente seduto davanti a una tastiera).52 I programmi interattivi normalmente bufferizzano per riga il loro output (cioè, scrivono in output una riga alla volta). I programmi non-interattivi attendono di aver riempito un buffer, il che può voler dire anche parecchie righe di output. Ecco un esempio della differenza: $ awk '{ print $1 + $2 }'
1 1
-| 2
2 3
-| 5
Ctrl-d
Ogni riga di output è stampata immediatamente. Si confronti questo comportamente con quello di questo esempio: $ awk '{ print $1 + $2 }' | cat
1 1
2 3
Ctrl-d
-| 2
-| 5
In questo caso, nessun output viene stampato finché non è stato battuto il
Ctrl-d, perché l’output è bufferizzato e inviato tramite
pipe al comando |
system(comando)Esegue il comando del sistema operativo comando e quindi
ritorna al programma awk.
Restituisce il codice di ritorno di comando.
Per esempio, inserendo il seguente frammento di codice in un programma
awk:
END {
system("date | mail -s 'awk completato' root")
}
all’amministratore di sistema viene inviato un messaggio di posta quando
il programma awk termina di elaborare l’input e inizia
l’elaborazione da eseguire alla fine dell’input.
Si noti che la ridirezione di print o printf in una
pipe è spesso sufficiente per ottenere lo stesso risultato.
Se è necessario eseguire parecchi comandi, è più efficiente
stamparli verso una pipe diretta alla shell:
while (ancora lavoro da fare)
print comando | "/bin/sh"
close("/bin/sh")
Tuttavia, nel caso che il programma awk sia interattivo,
system() è utile per eseguire grossi programmi autonomi,
come ad esempio la shell o un programma di modifica testi.
Alcuni sistemi operativi non consentono di implementare la funzione
system().
Richiamare system() in sistemi in cui non è disponibile provoca
un errore fatale.
NOTA: Quando si specifica l’opzione --sandbox, la funzione
system()è disabilitata (vedi la sezione Opzioni sulla riga di comando).
Nei sistemi aderenti allo standard POSIX, il codice di ritorno di un
comando è un numero contenuto in 16 bit. Il valore del codice di ritorno
passato alla funzione C exit() alla fine del programma è contenuto
negli 8 bit di valore più alto dei 16 bit (la metà sinistra) che compongono
il numero. I bit di valore più basso (la metà destra) indicano se il
processo è stato terminato da un segnale (bit 7), e, se questo è il caso,
il numero del segnale che ha provocato la terminazione (bit 0–6).
Tradizionalmente, la funzione system() di awk si è
semplicemente limitata a restituire il valore del codice di ritorno
diviso per 256 (ossia la metà sinistra del numero di 16 bit, spostata
a destra). In una situazione normale questo equivale a utilizzare il
codice di ritornodi system(), ma nel caso in cui il programma sia
stato terminato da un segnale, il valore diventa un numero frazionale in
virgola mobile.53 POSIX stabilisce che la chiamata a system() dall’interno
di awk dovrebbe restituire l’intero valore a 16 bit.
gawk si trova in qualche modo a metà strada.
I valori del codice di ritorno sono descritti nella
Tabella 9.5.
| Situazione | Valore codice di ritorno da system() |
|---|---|
| --traditional | Valore dalla funzione C system()/256 |
| --posix | Valore dalla funzione C system() |
| Uscita normale dal comando | Codice di ritorno del comando |
| Terminazione da un segnale | 256 + numero segnale "assassino" |
| Terminazione da un segnale con dump memoria | 512 + numero segnale "assassino" |
| Qualsiasi tipo di errore | -1 |
Tabella 9.5: Valori codici di ritorno da chiamata a system()
A partire dalla versione di agosto 2018, BWK awk si comporta
come gawk per il codice di ritorno della chiamata system().
|
Controllare la bufferizzazione dell’output con
system()
La funzione system("") # scrive l'output su disco
Avendo in mente le attese di un programmatore, sarebbe sensato che
BEGIN {
print "prima riga stampata"
system("echo system echo")
print "seconda riga stampata"
}
deve stampare: prima riga stampata system echo seconda riga stampata e non: system echo prima riga stampata seconda riga stampata Se |
Un programma è interattivo se il suo standard output è connesso a un dispositivo terminale. Ai giorni nostri, questo vuol dire davanti a uno schermo e a una tastiera.
In uno scambio di messaggi privato il Dr. Kernighan mi ha comunicato che questo modo di procedere è probabilmente errato.
Successivo: Funzioni di tempo, Precedente: Funzioni per stringhe, Su: Funzioni predefinite [Contenuti][Indice]