0Pricing
Linux Command Line & Bash Scripting Mastery · Lezione

Record, campi e separatori personalizzati in awk

Controlli i separatori dei campi di input e output per suddividere righe CSV, TSV e di log in colonne ordinate.

Record, campi e separatori personalizzati in awk è una lezione Linux Command Line & Bash Scripting Mastery gratuita su CoddyKit. Questa è la lezione 1 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Linux Command Line & Bash Scripting Mastery, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Linux Command Line & Bash Scripting Mastery include 4 lezioni in totale.

Cosa sono record e campi in awk?

awk legge l'input riga per riga. Ogni riga è chiamata record e ogni segmento separato da spazi bianchi all'interno della riga è chiamato campo.

  • $0: l'intero record corrente (la riga completa)
  • $1: il primo campo
  • $2: il secondo campo
  • $NF: l'ultimo campo (NF = numero di campi)

Per impostazione predefinita, awk divide i campi in corrispondenza di qualsiasi sequenza di spazi bianchi (spazi o tabulazioni). Per questo è subito utile per analizzare log, output di comandi e dati delimitati da spazi.

#!/usr/bin/env bash
# Show how awk sees records and fields
echo 'alice 30 engineer' | awk '{ print "Name:", $1, "Age:", $2, "Role:", $3 }'

# $NF is always the last field — regardless of how many there are
echo 'one two three four five' | awk '{ print "Last field:", $NF }'

Il separatore dei campi di input: FS

La variabile incorporata FS (Field Separator, separatore dei campi) indica ad awk come dividere ogni record in campi. Il valore predefinito è un singolo spazio, che attiva la modalità di suddivisione sugli spazi bianchi.

È possibile impostare FS in due modi:

  • Con l'opzione -F dalla riga di comando: awk -F':'
  • All'interno di un blocco BEGIN: BEGIN { FS = ":" }

I due metodi sono equivalenti. L'approccio con il blocco BEGIN è preferibile negli script più lunghi, perché mantiene la configurazione all'interno dello script, rendendolo più leggibile e portabile.

#!/usr/bin/env bash
# Parse /etc/passwd using ':' as the field separator
# Field 1 = username, field 3 = UID, field 7 = shell
echo 'root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin' \
  | awk -F':' '{ print $1, "UID="$3, "shell="$7 }'

Impostare FS nel blocco BEGIN

Per gli script più lunghi di una singola riga, inserire FS in un blocco BEGIN è la pratica standard. Il blocco BEGIN viene eseguito prima che awk legga qualsiasi input, quindi il separatore è pronto per il primo record.

Questo schema consente anche di impostare più variabili contemporaneamente, aggiungere commenti e mantenere la logica autonoma in un file di script.

Separatori comuni che si incontrano frequentemente:

  • Due punti :: /etc/passwd, /etc/shadow
  • Tabulazione \t: esportazioni TSV, output dei compilatori
  • Virgola ,: file CSV (semplici, senza campi tra virgolette)
  • Pipe |: alcuni formati di log, dump di database
#!/usr/bin/env bash
# awk script using BEGIN to set FS for TSV input
printf 'alice\t30\tengineer\nbob\t25\tdesigner\ncarol\t35\tmanager\n' \
  | awk 'BEGIN { FS = "\t" } { printf "%-10s age=%-3s role=%s\n", $1, $2, $3 }'

Analizzare i file CSV con awk

CSV (valori separati da virgole) è uno dei formati di dati più comuni nell'ingegneria della shell. Impostando FS="," si indica ad awk di usare le virgole come delimitatori.

Importante: la gestione CSV incorporata in awk non tiene conto dei campi tra virgolette che contengono virgole (ad esempio "Smith, John"). Per i CSV semplici, senza virgole tra virgolette, funziona perfettamente. Per i CSV conformi a RFC 4180 con campi tra virgolette, usi un parser CSV apposito oppure miller/csvkit.

Un'attività comune nel mondo reale consiste nell'estrarre colonne specifiche e filtrare le righe in base al valore: entrambe le operazioni sono banali con awk una volta impostato FS.

#!/usr/bin/env bash
# Simple CSV: extract name and salary columns, filter salary > 50000
data='name,department,salary
alice,engineering,95000
bob,marketing,48000
carol,engineering,112000
dave,hr,45000'

echo "$data" | awk -F',' '
  NR == 1 { next }          # skip header row
  $3 > 50000 { print $1, "earns", $3 }
'

Separatori di campo composti da più caratteri ed espressioni regolari

Il valore di FS di awk non è limitato a un singolo carattere: può essere un'espressione regolare. Questo è utile nei formati di log reali, in cui i campi sono separati da delimitatori di lunghezza variabile.

Esempi di separatori basati su espressioni regolari:

  • FS = "[,;]": divide in corrispondenza di una virgola o di un punto e virgola
  • FS = "[ \t]+": divide in corrispondenza di uno o più spazi/tabulazioni (come l'impostazione predefinita, ma in modo esplicito)
  • FS = "::": divide in corrispondenza di una doppia virgola letterale
  • FS = "\\|": divide in corrispondenza del carattere pipe (che deve essere sottoposto a escape)

Quando FS è un'espressione regolare, awk (gawk) la tratta come un pattern, non come una stringa letterale.

#!/usr/bin/env bash
# Log lines with mixed delimiters: split on " | " or "::" or ","
# Here we split on one or more spaces or pipe characters
printf '2024-01-15 | ERROR | disk full | /dev/sda1\n2024-01-15 | INFO  | startup ok | main\n' \
  | awk -F' \\| ' '{ printf "date=%-12s level=%-6s msg=%s\n", $1, $2, $3 }'

# Split on multiple possible delimiters using character class
echo 'alpha,beta;gamma,delta;epsilon' \
  | awk -F'[,;]' '{ for(i=1; i<=NF; i++) print i": "$i }'

Il separatore dei campi di output: OFS

OFS (Output Field Separator, separatore dei campi di output) controlla ciò che awk inserisce tra i campi quando si ricostruisce un record con print. Il valore predefinito è un singolo spazio.

Il punto fondamentale è che OFS viene inserito solo tra i campi quando si usa la sintassi con la virgola in print oppure quando si assegna un valore a un campo e awk ricostruisce $0. Se si concatenano gli elementi con spazi nel codice sorgente, OFS non viene usato.

  • print $1, $2, $3: le virgole attivano OFS tra i campi
  • print $1 " " $2: spazio esplicito, OFS ignorato

Uno schema comune consiste nel leggere un CSV, trasformarlo e scrivere un TSV impostando FS="," e OFS="\t".

#!/usr/bin/env bash
# Convert CSV to TSV using FS and OFS
data='alice,30,engineer
bob,25,designer
carol,35,manager'

echo "$data" | awk 'BEGIN { FS=","; OFS="\t" } { print $1, $2, $3 }'

echo '---'

# OFS also applies when you modify a field — awk rebuilds $0 with OFS
echo 'alice,30,engineer' | awk 'BEGIN { FS=","; OFS=" | " } { $1=$1; print $0 }'

Forzare awk a ricostruire $0 con OFS

Esiste un accorgimento sottile ma importante: assegnare un valore a qualsiasi campo (anche assegnare un campo a sé stesso, $1=$1) forza awk a ricostruire $0 unendo tutti i campi con OFS.

Questo è il modo idiomatico per riformattare i delimitatori di un record senza stampare manualmente ogni campo:

  • Impostare FS sul delimitatore di input
  • Impostare OFS sul delimitatore di output desiderato
  • Forzare la ricostruzione con $1=$1
  • Stampare $0

Questo approccio funziona con un numero qualsiasi di campi ed evita di scrivere esplicitamente $1, $2, $3, ....

#!/usr/bin/env bash
# Reformat a pipe-delimited file to comma-separated WITHOUT listing every field
printf 'alice|30|engineer|london\nbob|25|designer|paris\ncarol|35|manager|berlin\n' \
  | awk 'BEGIN { FS="|"; OFS="," } { $1=$1; print $0 }'

# Useful when you don't know how many fields there are:
printf 'a|b|c|d|e|f|g\n1|2|3|4|5|6|7\n' \
  | awk 'BEGIN { FS="|"; OFS="\t" } { $1=$1; print $0 }'

Il separatore dei record: RS

Così come FS suddivide i campi all’interno di un record, RS (Record Separator) definisce ciò che separa i record tra loro. Per impostazione predefinita, RS è un carattere di nuova riga, quindi awk elabora una riga alla volta.

Modificando RS è possibile eseguire una potente elaborazione di record su più righe:

  • RS="" — modalità paragrafo: le righe vuote separano i record (i campi possono estendersi su più righe)
  • RS=";" — suddivisione in corrispondenza dei punti e virgola (utile per i dump SQL)
  • RS="\n" — nuova riga esplicita (impostazione predefinita)

In modalità paragrafo (RS=""), FS continua a essere usato per suddividere i campi all’interno del record su più righe; inoltre, le nuove righe all’interno di un record vengono automaticamente trattate come separatori di campo.

#!/usr/bin/env bash
# Paragraph mode: each blank-line-separated block is one record
# Useful for processing structured text blocks (e.g., stanzas, config sections)
data='Name: Alice
Role: Engineer
City: London

Name: Bob
Role: Designer
City: Paris'

echo "$data" | awk 'BEGIN { RS=""; FS="\n" } {
  print "Record", NR":"
  for (i=1; i<=NF; i++) print "  ", $i
  print ""
}'

Il separatore dei record di output: ORS

ORS (Output Record Separator) viene stampato dopo ogni istruzione print. Per impostazione predefinita è una nuova riga (\n), motivo per cui ogni print viene visualizzato su una nuova riga.

Modificando ORS è possibile:

  • Unire i record su una sola riga: ORS=" "
  • Aggiungere righe vuote tra i record di output: ORS="\n\n"
  • Creare formati di output personalizzati, come frammenti JSON o XML

Noti che printf non usa ORS: si applica solo all’istruzione print semplice. Usi printf quando ha bisogno di un controllo completo sulla formattazione.

#!/usr/bin/env bash
# Join all matching lines onto one line by setting ORS to a space
printf 'apple\nbanana\ncherry\ndate\n' | awk '{ ORS=" " } { print $0 }'
echo  # final newline

# Add a blank line after every output record for readability
printf 'alice 30 engineer\nbob 25 designer\ncarol 35 manager\n' \
  | awk 'BEGIN { ORS="\n\n" } { print $1, "is a", $3 }'

Esempio pratico: analizzare i log di accesso di Apache

I log di accesso di Apache/nginx hanno un formato noto con campi delimitati da spazi. Alcuni campi, come il timestamp, contengono spazi e sono racchiusi tra parentesi quadre o virgolette, rendendo complicata la suddivisione diretta in campi con awk.

Un approccio pratico consiste nell’usare un FS basato su un’espressione regolare che tenga conto della struttura, oppure nell’estrarre campi specifici in base alla posizione, conoscendo il formato esatto.

I campi del Combined Log Format sono, in linea di massima:

  1. Indirizzo IP del client
  2. Ident (solitamente -)
  3. Utente autenticato (solitamente -)
  4. Timestamp (tra parentesi quadre, conta come un unico token)
  5. Metodo+percorso+protocollo della richiesta (tra virgolette)
  6. Codice di stato HTTP
  7. Byte della risposta
#!/usr/bin/env bash
# Parse a simulated Apache Combined Log Format line
# Extract: IP, status code, bytes, and request path
logs='192.168.1.10 - alice [15/Jan/2024:10:23:45 +0000] "GET /api/users HTTP/1.1" 200 1523
10.0.0.5 - - [15/Jan/2024:10:23:46 +0000] "POST /login HTTP/1.1" 401 89
172.16.0.3 - bob [15/Jan/2024:10:23:47 +0000] "GET /dashboard HTTP/1.1" 200 8741'

echo "$logs" | awk '{
  ip     = $1
  status = $9
  bytes  = $10
  # Extract the request path from the quoted string in field 7
  split($7, parts, "/")
  path = "/" parts[2]
  printf "ip=%-15s status=%s bytes=%-6s endpoint=%s\n", ip, status, bytes, path
}'

Combinare FS, OFS, RS e ORS in una pipeline

Nella pratica dell’ingegneria delle shell, raramente si usano questi separatori isolatamente. Un modello comune di pipeline consiste nell’usare awk come convertitore di formato al centro della pipeline, trasformando un formato strutturato in un altro.

Punti chiave per combinare i separatori:

  • Impostare sempre insieme FS e OFS in BEGIN quando si convertono formati
  • Usare $1=$1 per attivare la ricostruzione di $0 quando si desidera riformattare tutti i campi senza elencarli
  • Modificare RS solo quando i record si estendono effettivamente su più righe
  • Usare ORS per controllare la spaziatura tra i record di output
  • Preferire printf per una formattazione precisa; usare print quando è utile la terminazione automatica tramite ORS
#!/usr/bin/env bash
# Full pipeline: read a colon-delimited file,
# filter rows where field 3 (UID) >= 1000 (real users),
# then output as tab-separated: username, UID, home dir
echo 'root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
alice:x:1001:1001:Alice:/home/alice:/bin/bash
bob:x:1002:1002:Bob:/home/bob:/bin/zsh
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin' \
  | awk 'BEGIN { FS=":"; OFS="\t" } $3 >= 1000 { print $1, $3, $6 }'

Verifica delle conoscenze: OFS e ricostruzione dei campi

Verifichi la Sua comprensione del modo in cui OFS interagisce con l’assegnazione dei campi in awk.

Riepilogo della lezione: record, campi e separatori

Ora ha il pieno controllo sul modo in cui awk legge e scrive dati strutturati. Ecco un riepilogo delle quattro variabili separatore:

  • FS — separatore dei campi di input. Si imposta con -F o in BEGIN. Può essere un carattere, una stringa o un’espressione regolare. Valore predefinito: spazio bianco.
  • OFS — separatore dei campi di output. Viene inserito tra i campi nelle chiamate print $1, $2 e quando awk ricostruisce $0 dopo un’assegnazione a un campo. Valore predefinito: un singolo spazio.
  • RS — separatore dei record di input. Definisce ciò che separa i record (le righe). Valore predefinito: nuova riga. Impostarlo su una stringa vuota attiva la modalità paragrafo.
  • ORS — separatore dei record di output. Viene aggiunto dopo ogni print. Valore predefinito: nuova riga. Può essere modificato per unire le righe o aggiungere spaziatura.

Il modello più importante da ricordare è il seguente: impostare sia FS sia OFS in BEGIN, quindi usare $1=$1 per ricostruire $0 ogni volta che si desidera riformattare i delimitatori di tutti i campi senza codificare manualmente le posizioni. Questo modello funziona con file contenenti qualsiasi numero di colonne ed è alla base delle pipeline di conversione del formato basate su awk.

Domande Frequenti

La lezione «Record, campi e separatori personalizzati in awk» è gratuita?

Sì — il testo completo di «Record, campi e separatori personalizzati in awk» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Linux Command Line & Bash Scripting Mastery, passa a CoddyKit PRO. Il corso Linux Command Line & Bash Scripting Mastery include 4 lezioni in totale.

Cosa imparerò in «Record, campi e separatori personalizzati in awk»?

Controlli i separatori dei campi di input e output per suddividere righe CSV, TSV e di log in colonne ordinate. Eserciti Linux Command Line & Bash Scripting Mastery con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Linux Command Line & Bash Scripting Mastery?

Non è richiesta alcuna esperienza precedente. Linux Command Line & Bash Scripting Mastery su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 1 di 4.

Quanto tempo richiede la lezione «Record, campi e separatori personalizzati in awk»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Linux Command Line & Bash Scripting Mastery?

Sì. Ogni lezione Linux Command Line & Bash Scripting Mastery include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Record, campi e separatori personalizzati in awk
  2. Pattern, intervalli e blocchi BEGIN/END
  3. Aggregazione con array e raggruppamenti in awk
  4. Funzioni awk, formattazione con printf e generazione di report
← Torna a Linux Command Line & Bash Scripting Mastery