Successivo: , Su: Gestione File Dati   [Contenuti][Indice]


10.3.1 Trovare i limiti dei file-dati

Ognuna delle regole BEGIN ed END viene eseguita esattamente solo una volta, rispettivamente all’inizio e alla fine del programma awk (vedi la sezione I criteri di ricerca speciali BEGIN ed END). Una volta noi (gli autori di gawk) siamo venuti in contatto con un utente che erroneamemnte pensava che le regole BEGIN venissero eseguite all’inizio di ogni file-dati e le regole END alla fine di ogni file-dati.

Quando lo abbiamo informato che non era così, ci ha chiesto di aggiungere un nuovo criterio di ricerca speciale a gawk, chiamato BEGIN_FILE e END_FILE, che avesse il comportamento desiderato. Ci ha fornito anche il codice per far questo.

Non è stato necessario aggiungere a gawk questi criteri di ricerca speciali; il lavoro si può fare tranquillamente usando awk, come illustrato nel seguente programma di libreria. È strutturato in modo da chiamare due funzioni fornite dall’utente, a_inizio_file() e a_fine_file(), all’inizio e alla fine di ogni file-dati. Oltre a risolvere il problema in sole nove(!) righe di codice, questa soluzione è portabile; il programma funziona con qualsiasi implementazione di awk:

# transfile.awk
#
# Dare all'utente un aggancio per il passaggio
# da un file in input a quello successivo
#
# L'utente deve fornire le funzioni a_inizio_file() ed a_fine_file()
# ciascuna delle quali è invocata
# quando il file, rispettivamente,
# inizia e finisce.

FILENAME != _nome_file_vecchio {
    if (_nome_file_vecchio != "")
        a_fine_file(_nome_file_vecchio)
    _nome_file_vecchio = FILENAME
    a_inizio_file(FILENAME)
}

END { a_fine_file(FILENAME) }

Questo file [transfile.awk] dev’essere caricato prima del programma “principale” dell’utente, in modo che la regola ivi contenuta venga eseguita per prima.

Questa regola dipende dalla variabile di awk FILENAME, che cambia automaticamente per ogni nuovo file-dati. Il nome-file corrente viene salvato in una variabile privata, _nome_file_vecchio. Se FILENAME non è uguale a _nome_file_vecchio, inizia l’elaborazioone di un nuovo file-dati ed è necessario chiamare a_fine_file() per il vecchio file. Poiché a_fine_file() dovrebbe essere chiamato solo se un file è stato elaborato, il programma esegue prima un controllo per assicurarsi che _nome_file_vecchio non sia la stringa nulla. Il programma assegna poi il valore corrente di nome-file a _nome_file_vecchio e chiama a_inizio_file() per il file. Poiché, come tutte le variabili di awk, _nome_file_vecchio è inizializzato alla stringa nulla, questa regola viene eseguita correttamente anche per il primo file-dati.

Il programma contiene anche una regola END per completare l’elaborazione per l’ultimo file. Poiché questa regola END viene prima di qualsiasi regola END contenuta nel programma “principale”, a_fine_file() viene chiamata per prima. Ancora una volta, l’utilità di poter avere più regole BEGIN ed END dovrebbe risultare chiara.

Se lo stesso file-dati compare due volte di fila sulla riga di comando, a_fine_file() e a_inizio_file() non vengono eseguite alla fine del primo passaggio e all’inizio del secondo passaggio. La versione seguente risolve il problema:

# ftrans.awk --- gestisce il passaggio da un file dati al successivo
#
# L'utente deve fornire le funzioni a_inizio_file() ed a_fine_file()

FNR == 1 {
    if (_filename_ != "")
        a_fine_file(_filename_)
    _filename_ = FILENAME
    a_inizio_file(FILENAME)
}

END { a_fine_file(_filename_) }

Contare cose mostra come utilizzare questa funzione di libreria e come ciò semplifichi la scrittura del programma principale.

Allora perché gawk ha BEGINFILE e ENDFILE?

Ci si chiederà, probabilmente: perché, se le funzioni a_inizio_file() e a_fine_file() possono eseguire il compito, gawk prevede i criteri di ricerca BEGINFILE e ENDFILE?

Buona domanda. Normalmente, se awk non riesce ad aprire un file, questo fatto provoca un errore fatale immediato. In tal caso, per una funzione definita dall’utente non vi è alcun modo di affrontare il problema, giacché la chiamata verrebbe effettuata solo dopo aver aperto il file e letto il primo record. Quindi, la ragione principale di BEGINFILE è quella di dare un “aggancio” per gestire i file che non posso essere elaborati. ENDFILE esiste per simmetria, e perché consente facilmente una pulizia "file per file". Per maggiori informazioni si faccia riferimento alla I criteri di ricerca speciali BEGINFILE ed ENDFILE.


Successivo: , Su: Gestione File Dati   [Contenuti][Indice]