- awk è uno strumento e linguaggio di scripting orientato all'elaborazione di testo per righe e colonne, ideale per filtrare, trasformare e analizzare gli output di comandi e file.
- Consente di definire modelli e azioni combinando espressioni regolari, variabili speciali come $0, $1, NF o NR e funzioni come length, substr o match per creare filtri molto precisi.
- awk funziona comodamente con delimitatori e campi utilizzando FS, OFS e opzioni come -F, e può formatear output con print e printf, eseguire operazioni matematiche e gestire variabili con -v.
- È possibile creare script awk completi che automatizzano attività complesse, tra cui ricerche e sostituzioni con gsub, calcoli avanzati e generazione di report da comandi quali ps, df o file di sistema.

Quando inizi a prendere sul serio la console Linux Scoprirai che lavorare con il testo non significa solo guardare i file con cat E questo è tutto. Non appena entri in i registri Per elenchi enormi di processi, output di comandi o file CSV, hai bisogno di qualcosa di molto più potente per filtrare, trasformare e riepilogare i dati senza impazzire.
Ecco dove entra in gioco awk : un comando che, ben più di un semplice filtro, è praticamente un linguaggio di programmazione orientato all'elaborazione del testo. Permette di cercare modelli, selezionare colonne, eseguire calcoli, definire condizioni, utilizzare variabili, cicli, funzioni... e persino scrivere script completi. In questo tutorial su awk per Linux, lo esploreremo in dettaglio, dalle basi agli utilizzi più avanzati, integrando diversi esempi pratici da riga di comando.
Cos'è awk e a cosa serve in Linux?
Awk è uno strumento da riga di comando e un linguaggio di scripting progettato per analizzare testi strutturati in righe e campi. Il suo nome deriva dalle iniziali dei suoi creatori (Aho, Weinberger e Kernighan) ed esiste dalla fine degli anni '70, ma rimane un componente chiave in qualsiasi ambiente Unix o GNU/Linux (ad esempio, per eseguire vecchi sistemi Unix sul proprio PC ).
La filosofia alla base di awk è molto semplice : scorre un file (o l'output di un comando) riga per riga, divide ogni riga in colonne utilizzando un separatore, verifica se una condizione è soddisfatta e, in tal caso, esegue un'azione. Se non si specifica una condizione, l'azione viene applicata a tutte le righe; se non si specifica un'azione, l'azione predefinita è quella di stampare l'intera riga.
Con questo semplice meccanismo puoi fare cose davvero incredibili.: dal mostrare solo alcune colonne di ps o df...per calcolare totali, filtrare in base a modelli complessi con espressioni regolari, sostituire testo, formattare report, lavorare con file CSV o persino scrivere script di diverse decine di righe.
Sebbene awk possa ricordare un po' grep o sed , il suo approccio è più strutturato: considera le righe come record e le parole (o i campi) come colonne, con variabili interne e un mini-linguaggio che lo rende ideale per elaborare rapidamente dati tabellari.
In pratica, se si vuole iniziare a scrivere script shell adeguati...È quasi obbligatorio conoscere awk insieme ad altre utilità come sed, grep, cut e compagnia. Sono gli elementi fondamentali dell'elaborazione testi in Linux.
Installa ed esegui awk (gawk) sul tuo sistema
Nella maggior parte delle distribuzioni GNU/Linux moderneawk è già installato di default, solitamente nella variante GNU awk (gawkPuoi verificarlo con:
awk --version
Se per qualche motivo non lo hai installato , su Debian, Ubuntu e derivati puoi usare il gestore di pacchetti:
sudo apt update && sudo apt install gawk
È disponibile anche su macOS . Puoi usare la versione di sistema o installare una versione aggiornata tramite Homebrew.
brew install gawk
Una volta installato, awk si usa sempre allo stesso modo : gli si passano le istruzioni tra virgolette singole e un file (oppure si reindirizza l'output di un altro comando). Ad esempio:
awk '{print}' archivo.txt
È possibile utilizzare awk anche come interprete di script , specificando il percorso del file eseguibile nella prima riga del file:
#!/usr/bin/awk -f
e poi eseguendo il copione direttamente o con awk -f script.awk.
Sintassi di base: modelli e azioni

La struttura minima di awk è:
awk 'patrón { acción }' fichero
Ogni riga del file viene confrontata con il pattern . Se corrisponde, viene eseguita l'azione racchiusa tra parentesi graffe. Se si omette il pattern, l'azione viene applicata a tutte le righe. Alcuni concetti chiave:
Variabili speciali a cui fare riferimento per ciascuna riga :
$0: la linea completa.$1, $2, $3, …: campi (colonne) della riga, separati dal delimitatore definito.NF: numero di campi nella riga corrente.NR: numero di registrazione corrente (numero di riga globale).FNR: numero di riga all'interno del file corrente, utile quando si elaborano più file.
Istruzioni speciali :
BEGIN { … }: blocco che viene eseguito prima di leggere qualsiasi riga.END { … }: blocco che viene eseguito dopo aver elaborato tutte le righe.
Comandi di output più comuni :
print: stampa gli argomenti separati dal separatore di output (OFS(per impostazione predefinita, uno spazio).printf: simile aprintfIn C, consente una formattazione dettagliata senza aggiungere interruzioni di riga automatiche.
Esempio minimo per stampare un file esattamente così com'è, come se fosse cat:
awk '{print}' archivo.txt
Oppure, se si desidera visualizzare anche la lunghezza di ogni riga :
awk '{print length, "\t", $0}' archivo.txt
Lavorare con colonne e separatori in awk
Uno degli usi principali di awk è la manipolazione delle colonne da output di comando come ps, df o file come /etc/passwdPer impostazione predefinita, awk considera qualsiasi spazio o tabulazione come separatore, ma è possibile utilizzare praticamente qualsiasi delimitatore.
Seleziona colonne specifiche
Immagina l'uscita di ps con più colonne (PID, TTY, TIME, CMD…)Se vuoi solo vedere i PID, basta:
ps | awk '{print $1}'
Se sei interessato alla seconda colonna (ad esempio, il TTY) :
ps | awk '{print $2}'
E se vuoi saltare la prima riga (l'intestazione) , puoi filtrare per numero di record:
ps | awk 'NR>1 {print $1}'
L'idea è molto semplice.: ogni numero dopo il simbolo $ Si riferisce alla colonna corrispondente, sempre rispetto al separatore corrente.
Cambia il delimitatore con -F e con FS
Molti file di sistema non sono separati da spazi.ma da altri SimboliUn classico è /etc/passwddove i campi sono separati da :Per elaborare quel file per colonne, hai due opzioni: l'opzione -F sulla riga di comando o sulla variabile FS all'interno di un blocco BEGIN.
Utilizzo dell'opzione -F sulla riga di comando :
cat /etc/passwd | awk -F ":" '{print $1}'
Questo esempio mostra solo i nomi utente (primo campo) perché il separatore è ora :Se desideri anche l'UID e il GID (campi 3 e 4), semplicemente:
cat /etc/passwd | awk -F ":" '{print $1, $3, $4}'
Il problema con questo comando è che l'output è continuo se non si definiscono separatori espliciti, quindi è possibile aggiungere spazi o tabulazioni manualmente:
cat /etc/passwd | awk -F ":" '{print $1 " " $3 " " $4}'
Se vuoi un risultato più tabulato, Puoi usare \t per inserire le tabulazioni:
cat /etc/passwd | awk -F ":" '{print $1 "\t" $3 "\t" $4}'
L'alternativa, utilizzando FS in un blocco BEGIN, consente di impostare il separatore all'interno dello script awk stesso:
cat /etc/passwd | awk 'BEGIN { FS=":" } {print $1 "\t" $3 "\t" $4}'
Entrambi gli approcci sono funzionalmente equivalentisebbene usando BEGIN {FS=...} Di solito è più pulito scrivere script .awk riutilizzabili.
FS e OFS: separatori di input e output
Oltre a FS (Field Separator), awk ha OFS (Output Field Separator)che definisce come i campi vengono separati quando si utilizza print con virgole:
cat /etc/passwd | awk 'BEGIN { FS=":"; OFS=" - " } {print $1, $3, $4}'
In questo caso, leggi con : ma tu scrivi con - , generando un output come:
root - 0 - 0
daemon - 1 - 1
...
Questa combinazione FS/OFS è molto utile per "riformattare" i dati , ad esempio per convertirli da un formato all'altro o per preparare output leggibili da esportare poi in un altro sistema.
Ottieni l'ultimo campo con $NF (e quelli precedenti)
In molti output di comandoIl campo che ti interessa è alla fine, ma il numero esatto di colonne varia. È lì che $NF (Numero di campi) ti semplifica la vita: è sempre l'ultimo campo nella riga corrente.
Per esempio, in /etc/shells I percorsi shell validi appaiono alla fine di ogni rigaA volte nella seconda colonna, a volte nella terza, ecc. Per stampare solo il nome della shell (la parte dopo l'ultima barra):
awk -F "/" '/^\// {print $NF}' /etc/shells
Se poi vuoi mantenere solo valori univoci (senza duplicati), puoi concatenare con uniq:
awk -F "/" '/^\// {print $NF}' /etc/shells | uniq
E se quello che ti interessa è il penultimo elemento del percorso (ad esempio, la directory precedente), puoi usare $(NF-1) o $(NF-2):
awk -F "/" '/^\// {print $(NF-1)}' /etc/shells
awk -F "/" '/^\// {print $(NF-2)}' /etc/shells
Filtrare le linee con modelli, lunghezza e condizioni logiche
Awk è perfetto quando vuoi limitarti solo a determinate righe in base a modelli di testo, colonne specifiche o condizioni numeriche. Combina espressioni regolari, operatori logici e funzioni come length per realizzare filtri molto precisi.
Filtra per modelli ed espressioni regolari
Il modo più diretto per filtrare in base al contenuto è inserire l'espressione regolare tra barre oblique appena prima delle parentesi graffe:
awk '/patrón/ {print}' archivo.txt
Ad esempio, con la partenza di df È possibile visualizzare solo le righe che iniziano con una barra (file system montati):
df | awk '/^\// {print}'
Se si desidera una partizione specifica, ad esempio /dev/sda5:
df | awk '/^\/dev\/sda5/ {print}'
Puoi anche filtrare in base ai modelli all'inizio o alla fine della riga utilizzando ^ y $:
awk '/^tmpfs/ {print}' archivo.txt
awk '/\/shm$/ {print}' archivo.txt
E combinare diversi criteri con l'operatore logico &&Ad esempio, le linee che iniziano con tmpfs e termina in /dev/shm:
df | awk '/\/shm$/ && /^tmpfs/ {print}'
Filtra per colonne e mostra solo ciò che ti interessa
Spesso si desidera filtrare non solo le righe, ma anche le colonne.Continuando con df -h, puoi mostrare solo i file system reali (^/) e poi mantieni le colonne 1, 2 e 3:
df -h | awk '/^\// {print $1 "\t" $2 "\t" $3}'
Awk permette persino di manipolare i campi al volo . Ad esempio, è possibile sommare le colonne 2 e 3 (utilizzate + disponibili) per visualizzare una "capacità totale" calcolata:
df -h | awk '/^\// {print $1 "\t" $2 + $3}'
Se si desidera aggiungere l'unità letterale "G" alla fine del risultato :
df -h | awk '/^\// {print $1 "\t" $2 + $3 "G"}'
Filtra per lunghezza della riga usando length()
La funzione length() misura il numero di caratteri in una stringaDi solito viene utilizzato con $0 (riga intera), ma è possibile utilizzarlo anche con una colonna specifica.
Per mostrare solo le linee di /etc/shells con più di 9 caratteri:
awk 'length($0) > 9' /etc/shells
Se vuoi vedere la lunghezza di ogni riga :
awk '{print length, "\t", $0}' /etc/shells
È anche possibile filtrare per lunghezza e quindi stampare solo la lunghezza :
awk 'length($0) > 9 {print length}' /etc/shells
Combina più condizioni con && e if
Oltre all'utilizzo di espressioni regolari all'inizioÈ possibile scrivere condizioni complete all'interno del blocco utilizzando if, confronto e operatori logici.
Ad esempio, mostrando solo le linee di df -h che iniziano con t e la cui colonna 6 ha più di 8 caratteri:
df -h | awk '/^t/ && length($6) > 8 {print $0}'
Un altro caso tipico è la ricerca di processi tramite l'ultimo campo (comando eseguito) all'uscita di ps -efL'ultimo campo è $NFQuindi puoi usare:
ps -ef | awk '{ if ($NF == "firefox") print $0 }'
Se ti interessano solo il PID e il comando :
ps -ef | awk '{ if ($NF == "firefox") print $2, $NF }'
Linee di controllo con NR, intervalli e lunghezza del campo
La variabile NR (Number of Record) conta quante righe sono state lette finora (a livello globale). Ciò consente di eseguire azioni comuni come saltare le intestazioni, stampare intervalli di righe specifici o visualizzare solo la prima riga.
Conta le righe e mostra solo la prima o la seconda
Per contare il numero totale di righe in un file senza usare wc -l Puoi fare:
awk 'END {print NR}' archivo.txt
Se si desidera stampare solo la prima riga :
awk 'NR==1 {print}' archivo.txt
E per mostrare solo la seconda riga :
awk 'NR==2 {print}' archivo.txt
Stampa a partire da una riga o un intervallo specifico
Per mostrare tutte le linee dalla terza in poi Puoi usare una condizione semplice con > o >=:
ps -aux | awk 'NR>2 {print}'
Se vuoi un intervallo, ad esempio le righe da 2 a 4 en /etc/shells:
cat /etc/shells | awk 'NR==2, NR==4 {print $0}'
È possibile stampare anche il numero di riga accanto al contenuto :
cat /etc/shells | awk 'NR==2, NR==4 {print NR, $0}'
Lunghezza dei campi specifici
Oltre a misurare la lunghezza delle linee completeÈ possibile verificare la lunghezza di una colonna specifica. Ad esempio, per vedere quanti caratteri il file system (colonna 1) ha nell'output di df -h:
df -h | awk '{print length($1) "\t" $1}'
Se vuoi saltare l'intestazione (prima riga), aggiunge NR>1:
df -h | awk 'NR>1 {print length($1) "\t" $1}'
Funzioni utili: substr, match, RSTART e RLENGTH
Awk include un buon assortimento di funzioni di testoDue dei più potenti per le ricerche avanzate sono substr y match, quest'ultimo accompagnato dalle variabili RSTART y RLENGTH.
Ritaglia il testo con substr()
La funzione substr(cadena, inicio) o substr(cadena, inicio, longitud) Permette di estrarre sottostringhe. Ad esempio, per rimuovere i primi 5 caratteri da ogni riga di /etc/shells:
cat /etc/shells | awk '{print substr($0, 5)}'
Se non si desidera elaborare la prima riga (ad esempio, un commento), è possibile utilizzare NR:
cat /etc/shells | awk 'NR>1 {print substr($0, 5)}'
Si noti che il primo parametro è la stringa (solitamente $0) e il secondo indica quale carattere vuoi iniziare a visualizzare.
Individuazione di modelli con match(), RSTART e RLENGTH
La funzione match(cadena, /regex/) cerca un'espressione regolare all'interno della stringaSe viene trovata una corrispondenza, restituisce la posizione iniziale (basata su 1) e popola due variabili:
RSTART: posizione in cui inizia il modello trovato.RLENGTH: durata della partita.
Ad esempio, per tutte le linee di ps -aux che contengono "cpu"È possibile visualizzare l'intera linea e la posizione in cui si trova il modello:
ps -aux | awk 'match($0, /cpu/) {print $0 " Contiene \"cpu\" en la posición " RSTART}'
Se vuoi anche conoscere le dimensioni del modello trovato, usa semplicemente RLENGTH all'uscita:
ps -aux | awk 'match($0, /cpu/) {print $0 " Posición=" RSTART " Longitud=" RLENGTH}'
Questo tipo di ricerca è ampiamente utilizzato nell'analisi testuale e nella bioinformatica , ad esempio sui file FASTA, dove si è interessati a individuare motivi specifici all'interno di sequenze.
Operazioni matematiche e variabili in awk
Awk non si limita alla visualizzazione del testo : permette di eseguire operazioni numeriche direttamente su campi, variabili interne o valori che gli vengono passati dalla riga di comando o dall'ambiente shell.
Definisci le variabili con -vy e usale in BEGIN
È possibile dichiarare le variabili con l'opzione -v quando si invoca awkAd esempio, moltiplicando due numeri fissi:
awk -v a="10" -v b="20" 'BEGIN {print "La multiplicación de a x b es", a*b}'
È anche possibile passare valori variabili dalla shell . Se in bash fai così:
a=1.5
b=4
Quindi puoi usarli in awk in questo modo :
awk -v a="$a" -v b="$b" 'BEGIN {print "La multiplicación de a x b es", a*b}'
Il blocco BEGIN viene utilizzato qui perché non stiamo elaborando alcun file ; vogliamo semplicemente eseguire il codice una sola volta e visualizzare il risultato.
Funzioni matematiche: sqrt e cicli for
Awk incorpora diverse funzioni matematiche standard.Come sqrt() per le radici quadrate. Ad esempio, la radice quadrata di 400:
awk 'BEGIN {print sqrt(400)}'
È possibile combinarlo anche con cicli for per generare elenchi completi:
awk 'BEGIN { for(i=1; i<=10; i++) print "La raíz cuadrada de", i*i, "es", i }'
Oppure scorri i valori decimali da 0 a 1 con piccoli incrementi :
awk 'BEGIN { for(i=0; i<=1; i=i+0.00001) print "La raíz cuadrada de", i*i, "es", i }'
Questo tipo di strutture fa sì che awk assomigli molto a un linguaggio tradizionale , sebbene il suo ambiente naturale rimanga il testo a colonne.
Scrivere ed eseguire script completi in awk
Quando i comandi awk iniziano a diventare lunghi Se si desidera riutilizzare trasformazioni complesse, la cosa più sensata da fare è salvarle in un file di script con estensione . .awk (anche se non è obbligatorio).
Un esempio tipico riguarda l'elaborazione dell'output di df per visualizzare solo determinate voci che soddisfano le condizioni relative allo spazio disponibile e formattare i risultati come una piccola tabella.
Immagina di volere quanto segue :
- Mostra solo i file system il cui nome inizia con "t" (per esempio
tmpfs). - Filtra quelli con capacità disponibile (colonna 4) maggiore di 6000K.
- Stampa solo l'unità (colonna 1) e la somma delle colonne 2 e 3 come spazio totale approssimativo.
Puoi creare uno script chiamato capacidad.awk con contenuti simili a questo (adattato e semplificato):
#!/usr/bin/awk -f
BEGIN { printf "%s\n", "Voy a extraer las partes que me interesan del comando df" }
BEGIN { printf "%s\t%s\n", "Unidad", "Capacidad disponible" }
/^t/ && $4 > 6000 {print $1 "\t" $2 + $3 "K"}
E poi eseguilo concatenando l'output di df :
df | awk -f capacidad.awk
Se vuoi migliorare l'aspetto del tavolo, puoi sostituire print by printf e utilizzare formati come %-12s (testo giustificato a sinistra in 12 caratteri) o %-23d (Numero decimale in 23 caratteri). Questo ti dà il controllo perfetto sull'allineamento delle colonne.
Trova e sostituisci il testo con gsub()
Awk può anche eseguire sostituzioni di testo simile a quello che faresti con sed, usando la funzione gsub() (sostituto globale).
La sintassi generale è:
gsub("texto_o_regex_a_buscar", "texto_de_reemplazo", destino)
Ad esempio, supponiamo un file geekland.txt con il testo "Geekland è il miglior blog tecnologico" e vuoi cambiare la G iniziale in g:
awk '{ gsub("G", "g", $0); print $0 }' geekland.txt
Se non si specifica il terzo parametro, la ricerca viene eseguita su $0 per impostazione predefinitaTuttavia, è molto comune limitare la sostituzione a una singola colonna:
df -h | awk '{ gsub("M", "G", $2); print $2 }'
In questo caso abbiamo cambiato solo l'unità M in G nella colonna 2Se vuoi anche mostrare la colonna 1 correttamente allineata, puoi combinarla con printf:
df -h | awk '{ gsub("M", "G", $2); printf "%-12s %-12s\n", $1, $2 }'
Questo schema di "modifica di una colonna e successiva stampa formattata" è estremamente utile nei report, nelle migrazioni di dati o per una rapida pulizia dell'output dei comandi.
Usi aggiuntivi: gatto infetto da steroidi ed esecuzione di comandi
Anche se può sembrare scioccoawk può agire come cat Migliorato, poiché può visualizzare un file aggiungendo informazioni extra (numeri di riga, lunghezze, ecc.).
Un esempio banale sarebbe :
awk '{print}' functions.php
Ma è anche possibile numerare le linee o applicare qualsiasi filtro senza bisogno di utilizzare altri strumenti.
Un altro fatto interessante è che awk può eseguire comandi di sistema utilizzando la funzione system()Ad esempio, per visualizzare la directory corrente:
awk 'BEGIN { system("pwd") }'
Non è una funzionalità molto comune negli script semplici , ma è utile sapere che esiste quando si sviluppano strumenti più complessi basati su awk.
Awk diventa un vero e proprio coltellino svizzero per il testo in Linux : permette di filtrare righe, selezionare e unire colonne, sostituire frammenti, misurare lunghezze, trovare modelli, sommare campi, generare piccoli report formattati e persino creare script completi che elaborano l'output di altri comandi. Una volta imparato a usarlo, diventa uno strumento indispensabile ogni volta che si lavora con il terminale e i dati strutturati.
Scrittore appassionato del mondo dei byte e della tecnologia in generale. Adoro condividere le mie conoscenze attraverso la scrittura, ed è quello che farò in questo blog, mostrarti tutte le cose più interessanti su gadget, software, hardware, tendenze tecnologiche e altro ancora. Il mio obiettivo è aiutarti a navigare nel mondo digitale in modo semplice e divertente.