Awk è un linguaggio di scripting general-purpose progettato per l’elaborazione avanzata del testo. Viene utilizzato principalmente come strumento di reporting e analisi.
A differenza di molti altri linguaggi di programmazione che sono procedurali, awk è data-driven, il che significa che si definisce un insieme di azioni da eseguire contro il testo di input. Prende i dati di input, li trasforma e invia il risultato allo standard output.
Questo articolo copre gli elementi essenziali del linguaggio di programmazione awk., Conoscere le basi di awk migliorerà significativamente la tua capacità di manipolare i file di testo sulla riga di comando.
Come funziona awk #
Esistono diverse implementazioni di awk. Useremo l’implementazione GNU di awk, che si chiama gawk. Sulla maggior parte dei sistemi Linux, l’interpreteawk
è solo un collegamento simbolico agawk
.
Record e campi #
Awk può elaborare file di dati testuali e flussi. I dati di input sono suddivisi in record e campi. Awk opera su un record alla volta fino al raggiungimento della fine dell’input., I record sono separati da un carattere chiamato separatore di record. Il separatore di record predefinito è il carattere di nuova riga, il che significa che ogni riga nei dati di testo è un record. Un nuovo separatore di record può essere impostato utilizzando la variabileRS
.
I record sono costituiti da campi separati dal separatore di campo. Per impostazione predefinita, i campi sono separati da uno spazio bianco, che include uno o più caratteri di tabulazione, spazio e nuova riga.
I campi in ogni record sono referenziati dal simbolo del dollaro ($
) seguito dal numero del campo, che inizia con 1., Il primo campo è rappresentato con $1
, il secondo con $2
, e così via. L’ultimo campo può anche essere referenziato con la variabile speciale $NF
. L’intero record può essere referenziato con $0
.
Ecco una rappresentazione visiva che mostra come fare riferimento a record e campi:
tmpfs 788M 1.8M 786M 1% /run/lock /dev/sda1 234G 191G 31G 87% /|-------| |--| |--| |--| |-| |--------| $1 $2 $3 $4 $5 $6 ($NF) --> fields|-----------------------------------------| $0 --> record
Awk program #
Per elaborare un testo conawk
, si scrive un programma che dice al comando cosa fare., Il programma consiste in una serie di regole e funzioni definite dall’utente. Ogni regola contiene una coppia di pattern e azioni. Le regole sono separate da nuova riga o punti e virgola (;
). In genere, un programma awk ha il seguente aspetto:
pattern { action }pattern { action }...
Quando awk
elabora i dati, se il modello corrisponde al record, esegue l’azione specificata su quel record. Quando la regola non ha motivo, tutti i record (linee) sono abbinati.
Un’azione awk è racchiusa tra parentesi graffe ({}
) e consiste in istruzioni., Ogni istruzione specifica l’operazione da eseguire. Un’azione può avere più di un’istruzione separata da nuova riga o punti e virgola (;
). Se la regola non ha alcuna azione, per impostazione predefinita viene stampato l’intero record.
Awk supporta diversi tipi di istruzioni, tra cui espressioni, condizionali, istruzioni di input, output e altro ancora. Le istruzioni awk più comuni sono:
-
exit
– Interrompe l’esecuzione dell’intero programma ed esce., -
next
– Interrompe l’elaborazione del record corrente e passa al record successivo nei dati di input. -
print
– Stampa record, campi, variabili e testo personalizzato. -
printf
– Ti dà più controllo sul formato di output, simile a C e bashprintf
.
Quando si scrivono programmi awk, tutto dopo il segno hash (#)
e fino alla fine della riga è considerato un commento., Le righe lunghe possono essere suddivise in più righe usando il carattere di continuazione, backslash (\
).
Esecuzione di programmi awk #
Un programma awk può essere eseguito in diversi modi. Se il programma è breve e semplice, può essere passato direttamente il awk
interprete della riga di comando:
awk 'program' input-file...
Quando si esegue il programma sulla riga di comando, devono essere racchiusi tra virgolette singole (''
), in modo che la shell non interpretare il programma.,
Se il programma è ampio e complesso, è meglio metterlo in un file e utilizzare il -f
opzione di passare il file awk
comando:
awk -f program-file input-file...
Negli esempi riportati di seguito, useremo un file denominato “squadre.txt ” che assomiglia a quello qui sotto:
Bucks Milwaukee 60 22 0.732 Raptors Toronto 58 24 0.707 76ers Philadelphia 51 31 0.622Celtics Boston 49 33 0.598Pacers Indiana 48 34 0.585
Awk Patterns #
Patterns in awk controllano se l’azione associata deve essere eseguita o meno.,
Awk supporta diversi tipi di modelli, tra cui espressione regolare, espressione di relazione, intervallo e modelli di espressione speciali.
Quando la regola non ha pattern, ogni record di input viene abbinato. Ecco un esempio di una regola contenente solo un’azione:
awk '{ print $3 }' teams.txt
Il programma stamperà il terzo campo di ogni record:
6058514948
Regular expression patterns #
Un’espressione regolare o regex è un modello che corrisponde a un insieme di stringhe., I modelli di espressioni regolari Awk sono racchiusi in barre (//
):
/regex pattern/ { action }
L’esempio più semplice è un carattere letterale o una stringa corrispondente. Ad esempio, per visualizzare il primo campo di ogni record che contiene “0.5” è necessario eseguire il seguente comando:
awk '/0.5/ { print $1 }' teams.txt
CelticsPacers
Il modello può essere qualsiasi tipo di espressione regolare estesa., Ecco un esempio che stampa il primo campo se il record inizia con due o più cifre:
awk '/^/ { print $1 }' teams.txt
76ers
Relational expressions patterns #
I modelli di espressioni relazionali sono generalmente utilizzati per abbinare il contenuto di un campo o variabile specifico.
Per impostazione predefinita, i modelli di espressioni regolari vengono confrontati con i record. Per abbinare una regex a un campo, specificare il campo e utilizzare l’operatore di confronto “contain” (~
) contro il modello.,
Per esempio, per stampare il primo campo di ogni record di cui il secondo campo contiene il valore “ia”, devi digitare:
awk '$2 ~ /ia/ { print $1 }' teams.txt
76ersPacers
Per corrispondenza campi che non contengono un determinato pattern di utilizzare il !~
operatore:
awk '$2 !~ /ia/ { print $1 }' teams.txt
BucksRaptorsCeltics
È possibile confrontare le stringhe o numeri per le relazioni come, maggiore di, minore di, uguale, e così via., Il comando riportato di seguito viene stampato il primo campo di tutti i record in cui il terzo campo è maggiore di 50:
awk '$3 > 50 { print $1 }' teams.txt
BucksRaptors76ers
Gamma di modelli di #
la Gamma di modelli costituiti da due modelli separati da una virgola:
pattern1, pattern2
Tutti i record di partenza con un record che corrisponde al primo motivo fino a quando un record che corrisponde al secondo modello sono abbinati.,
Ecco un esempio che stamperà il primo campo di tutti i record a partire dal record incluso “Raptors” fino al record incluso “Celtics”:
awk '/Raptors/,/Celtics/ { print $1 }' teams.txt
Raptors76ersCeltics
I pattern possono anche essere espressioni di relazione. Il comando seguente stamperà tutti i record a partire da quello il cui quarto campo è uguale a 32 fino a quello il cui quarto campo è uguale a 33:
awk '$4 == 31, $4 == 33 { print $0 }' teams.txt
76ers Philadelphia 51 31 0.622Celtics Boston 49 33 0.598
I pattern di intervallo non possono essere combinati con altre espressioni di pattern.,
Special expression patterns #
Awk include i seguenti pattens speciali:
-
BEGIN
– Utilizzato per eseguire azioni prima che i record vengano elaborati. -
END
– Utilizzato per eseguire azioni dopo l’elaborazione dei record.
Il modelloBEGIN
viene generalmente utilizzato per impostare le variabili e il modelloEND
per elaborare i dati dai record come il calcolo.
Il seguente esempio stamperà “Avvia elaborazione.”, quindi stampare il terzo campo di ogni record e infine ” Terminare l’elaborazione.,”:
awk 'BEGIN { print "Start Processing." }; { print $3 }; END { print "End Processing." }' teams.txt
Start Processing6058514948End Processing.
Se un programma ha solo un pattern BEGIN
, le azioni vengono eseguite e l’input non viene elaborato. Se un programma ha solo un modelloEND
, l’input viene elaborato prima di eseguire le azioni della regola.
La versione Gnu di awk include anche altri due pattern specialiBEGINFILE
eENDFILE
, che consentono di eseguire azioni durante l’elaborazione dei file.,
Combinazione di pattern #
Awk consente di combinare due o più pattern utilizzando l’operatore logico AND (&&
) e l’operatore logico OR (||
).,
Ecco un esempio che utilizza il tag &&
operatore di stampa il primo campo di quei record in cui il terzo campo è maggiore di 50 e il quarto campo è a meno di 30:
awk '$3 > 50 && $4 < 30 { print $1 }' teams.txt
BucksRaptors
Built-in Variabili #
Awk ha un numero di variabili che contengono informazioni utili e consente di controllare il modo in cui il programma viene elaborato. Di seguito sono riportate alcune delle variabili incorporate più comuni:
-
NF
– Il numero di campi nel record., -
NR
– Il numero del record corrente. -
FILENAME
– Il nome del file di input attualmente elaborato. -
FS
– Separatore di campo. -
RS
– Separatore di record. -
OFS
– Separatore di campo di uscita. -
ORS
– Separatore record di uscita.,
Ecco un esempio che mostra come stampare il nome del file e il numero di righe (record):
awk 'END { print "File", FILENAME, "contains", NR, "lines." }' teams.txt
File teams.txt contains 5 lines.
Le variabili in AWK possono essere impostate in qualsiasi riga del programma. Per definire una variabile per l’intero programma, inserirla in un pattern BEGIN
.
Modifica del campo e del separatore di record #
Il valore predefinito del separatore di campo è un numero qualsiasi di caratteri di spazio o tabulazione. Può essere modificato impostando la variabileFS
.,
Per esempio, per impostare il separatore di campo .
si usa:
awk 'BEGIN { FS = "." } { print $1 }' teams.txt
Bucks Milwaukee 60 22 0Raptors Toronto 58 24 076ers Philadelphia 51 31 0Celtics Boston 49 33 0Pacers Indiana 48 34 0
Il separatore di campo può essere impostato anche per più di un carattere:
awk 'BEGIN { FS = ".." } { print $1 }' teams.txt
Quando si esegue awk one-liners sulla riga di comando, è possibile utilizzare anche il -F
opzione per cambiare il separatore di campo:
awk -F "." '{ print $1 }' teams.txt
per impostazione predefinita, il separatore di record è un carattere di newline e può essere modificato utilizzando il RS
variabile.,
Ecco un esempio che mostra come modificare il separatore di record .
:
awk 'BEGIN { RS = "." } { print $1 }' teams.txt
Bucks Milwaukee 60 22 0732 Raptors Toronto 58 24 0707 76ers Philadelphia 51 31 0622Celtics Boston 49 33 0598Pacers Indiana 48 34 0585
Awk Azioni #
Awk azioni sono racchiusi tra parentesi graffe ({}
) e viene eseguito quando il modello corrisponde. Un’azione può avere zero o più istruzioni. Più istruzioni vengono eseguite nell’ordine in cui appaiono e devono essere separate da nuova riga o punti e virgola (;
).,
Esistono diversi tipi di istruzioni di azione supportate in awk:
- Espressioni, come l’assegnazione delle variabili, gli operatori aritmetici, gli operatori di incremento e decremento.
- istruzioni di Controllo, utilizzato per controllare il flusso del programma (
if
for
while
switch
e di più) - Uscita dichiarazioni, ad esempio
print
eprintf
. - Dichiarazioni composte, per raggruppare altre dichiarazioni.,
- Istruzioni di input, per controllare l’elaborazione dell’input.
- Istruzioni di cancellazione, per rimuovere gli elementi dell’array.
L’istruzione print
è probabilmente l’istruzione awk più utilizzata. Stampa un output formattato di testo, record, campi e variabili.
Quando si stampano più elementi, è necessario separarli con virgole., Ecco un esempio:
awk '{ print $1, $3, $5 }' teams.txt
stampato elementi sono separati da spazi:
Bucks 60 0.732Raptors 58 0.70776ers 51 0.622Celtics 49 0.598Pacers 48 0.585
Se non si usa la virgola, non ci sarà spazio tra gli elementi:
awk '{ print $1 $3 $5 }' teams.txt
Il materiale stampato sono concatenate:
Bucks600.732Raptors580.70776ers510.622Celtics490.598Pacers480.585
Quando print
viene usato senza argomenti, per impostazione predefinita print $0
. Il record corrente viene stampato.,
Per stampare un testo personalizzato, è necessario citare il testo con caratteri di virgolette doppie:
awk '{ print "The first field:", $1}' teams.txt
The first field: BucksThe first field: RaptorsThe first field: 76ersThe first field: CelticsThe first field: Pacers
È anche possibile stampare i caratteri speciali, come nuova riga:
awk 'BEGIN { print "First line\nSecond line\nThird line" }'
First lineSecond lineThird line
printf
istruzione dà più controllo sopra il formato di output., id=”aa8cfd3cbd”>
printf
non creare un a capo dopo ogni record, in modo da stiamo usando \n
:
1. Bucks Milwaukee 60 22 0.732 2. Raptors Toronto 58 24 0.707 3. 76ers Philadelphia 51 31 0.622 4. Celtics Boston 49 33 0.598 5. Pacers Indiana 48 34 0.585
Il comando riportato di seguito consente di calcolare la somma dei valori memorizzati nel terzo campo in ogni riga:
awk '{ sum += $3 } END { printf "%d\n", sum }' teams.txt
266
Ecco un altro esempio che mostra come utilizzare le espressioni e istruzioni di controllo per stampare i quadrati dei numeri da 1 a 5:
awk 'BEGIN { i = 1; while (i < 6) { print "Square of", i, "is", i*i; ++i } }'
Square of 1 is 1Square of 2 is 4Square of 3 is 9Square of 4 is 16Square of 5 is 25
Una riga di comandi come quello di cui sopra sono più difficili da capire e gestire., Quando si scrivono programmi più lunghi, è necessario creare un file di programma separato:
BEGIN { i = 1 while (i < 6) { print "Square of", i, "is", i*i; ++i } }
Eseguire il programma, passando il nome del file per il awk
interprete:
awk -f prg.awk
È anche possibile eseguire un programma awk come un file eseguibile utilizzando la shebang direttiva e l’impostazione del awk
interprete:
#!/usr/bin/awk -fBEGIN { i = 1 while (i < 6) { print "Square of", i, "is", i*i; ++i } }
Salvare il file e renderlo eseguibile :
chmod +x prg.awk
ora È possibile eseguire il programma inserendo:
./prg.awk
Utilizzo di Variabili di Shell in Awk Programmi #
Se si utilizza il tag awk
comando nella shell script, è probabile che avrete bisogno di passare una variabile di shell per il awk programma. Un’opzione è quella di racchiudere il programma con virgolette doppie anziché singole e sostituire la variabile nel programma., Tuttavia, questa opzione renderà il tuo programma awk più complesso in quanto dovrai sfuggire alle variabili awk.
Il modo consigliato per utilizzare le variabili di shell nei programmi awk è assegnare la variabile di shell a una variabile awk. Ecco un esempio:
num=51
awk -v n="$num" 'BEGIN {print n}'