INIZIA e FINE con il comando awk


13

Secondo il manuale di awk, BEGIN ed END non sono usati per abbinare l'input, ma piuttosto per fornire informazioni di avvio e pulizia allo script di awk. Ecco l'esempio dato:

ls -l | \
awk 'BEGIN { print "Files found:\n" } /\<[a|x].*\.conf$/ { print $9 }'
Files found:
amd.conf
antivir.conf
xcdroast.conf
xinetd.conf

In primo luogo questo stampa una stringa per l'output. Quindi controlla l'input per una corrispondenza del modello, in cui l'input inizia con a o x seguito da un carattere una o più volte seguito da .conf. Per ogni corrispondenza, viene stampata la nona colonna.

Il fatto che siamo costretti a usare inizia qui, significa che awk può usare solo al massimo una funzione di stampa che contiene BEGIN o END? In caso contrario, perché non possiamo semplicemente utilizzare la funzione di stampa all'inizio senza la parola chiave BEGIN? Sembra che INIZIARE sia superfluo.


Basta eseguire il comando senza BEGIN per rispondere alla tua domanda, dimostrando che non è superfluo e che otterrai un risultato diverso.
ms

Risposte:


11

Non BEGINè superfluo. Se non si specifica BEGINpoi la printsarebbero stati giustiziati per ogni linea di input.

Citando dal manuale :

Una BEGINregola viene eseguita una sola volta, prima di leggere il primo record di input. Allo stesso modo, una ENDregola viene eseguita una sola volta, dopo aver letto tutto l'input.

$ seq 5 | awk 'BEGIN{print "Hello"}/4/{print}'   # Hello printed once
Hello
4
$ seq 5 | awk '{print "Hello"}/4/{print}'        # Hello printed for each line of input
Hello
Hello
Hello
Hello
4
Hello
$

7

awkelabora ogni riga di input per le espressioni fornite nel corpo diverse da BEGINe ENDblocchi. Nel caso di BEGINe ENDblocchi, awkelaborerà le istruzioni solo una volta, prima che abbia inizio l'elaborazione dell'input e dopo che sia stata eseguita l'elaborazione dell'input rispettivamente. Senza il BEGINblocco, non solo non sareste in grado di stampare informazioni singole come le intestazioni, ma non potreste inizializzare in modo efficiente alcune delle variabili richieste dal corpo. Inoltre, FYI, un awkprogramma può avere più BEGINe ENDblocchi.


2

awkesegue ogni blocco solo quando il modello prima corrisponde. Il modello vuoto (solo blocco) corrisponde a ogni riga. BEGINe ENDsono schemi speciali che corrispondono all'inizio e alla fine del file (analogo al significato di ^e $in direzione orizzontale).

Se si desidera eseguire qualcosa prima di leggere il file, utilizzare BEGIN. Ad esempio, inizializzazione di contatori o qualcosa del genere. ENDpotrebbe quindi raccogliere i risultati.


0

Nell'esempio dato, che penso sia semplificato per chiarezza pedagogica, hai ragione nel dire che è superfluo. È possibile ottenere gli stessi risultati senza utilizzare BEGIN.

1 == NR            { print "Files found:\n" }
/\<[a|x].*\.conf$/ { print $9               }

produrrebbe gli stessi risultati poiché l'istruzione print è vincolata solo alla prima riga di input.

Detto questo, i blocchi BEGINe ENDsono strumenti incredibilmente potenti. Come menzionato da altre soluzioni, è possibile utilizzare il BEGINblocco per inizializzare variabili o altre routine che devono essere eseguite una sola volta ma può anche essere utilizzato per eseguire i comandi Awk quando non ci sono file da elaborare. Un semplice esempio:

BEGIN { print sqrt(12/4) }

Puoi vedere un esempio più serio di programmazione in Awk senza elaborare alcun input qui .

Allo stesso modo, il ENDblocco è estremamente utile per eseguire calcoli e riepilogare tutti gli input. Questo non può essere fatto (di solito) senza prima lettura in tutti i dati. Un semplice esempio di input riassuntivo è disponibile qui

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.