Chiameremo il linguaggio AWK e l'eseguibile che interpreta i programmi AWK awk o gawk.
Un programma AWK è composto da coppie pattern-azione
pattern1 { action1 }
pattern2 { action2 }
...
Un pattern può essere un'espressione regolare con cui confrontare l'input. Può anche essere una qualsiasi espressione che produce un valore vero/falso.
Un'azione è uno o più comandi AWK. Le parentesi graffe che la racchiudono sono obbligatorie.
Se il risultato del pattern è vero, allora l'azione corrispondente viene valutata.
AWK analizza l'input come una serie di record. Ogni record viene suddiviso in zero o più campi.
Il comportamento predefinito è:
Il pattern può essere omesso, nel qual caso l'azione viene valutata per ogni record in input.
L'azione può essere omessa, nel qual caso l'azione predefinita è stampare il record corrente.
Ci sono due pattern speciali che vengono usati spesso.
BEGIN valuta l'azione associata prima che venga consumato qualsiasi input.END valuta l'azione associata dopo che tutto l'input è stato consumato.I campi si indicano con $1, $2, $3 e così via.
Il record corrente è $0.
Ecco alcune altre variabili predefinite usate di frequente.
RS è il separatore dei record in input.
Come accennato, il suo valore predefinito è un carattere di nuova riga.FS è il separatore dei campi in input.Queste variabili vengono spesso impostate nel blocco di azione BEGIN.
Queste variabili vengono impostate automaticamente da AWK durante l'esecuzione del programma.
NF memorizza il numero di campi nel record corrente.
$NF.NR memorizza il numero del record corrente.
NR contiene il numero totale di record elaborati finora.FNR memorizza il numero del record corrente del file di input corrente.
NR == FNR {action}
Significa «se il numero di record accumulato è uguale al numero di record del file corrente».
Questo può essere vero solo per i record del primo file di input.AWK usa lo stesso concetto di verità e falsità del linguaggio C.
0 è falso.Dato che AWK è un linguaggio di elaborazione di testo, i valori di verità vengono estesi alle stringhe.
"" è falsa.I commenti iniziano con il carattere # e si estendono fino alla fine della riga.
Nei sistemi Unix-like, /etc/passwd contiene informazioni sugli utenti.
Ogni utente è descritto su una riga separata, con i campi separati dai due punti.
Per elencare i nomi utente:
awk '
BEGIN { FS = ":" }
{ print $1 }
' /etc/passwd
Nota che l'azione {print $1} non ha un pattern, quindi viene eseguita per ogni record.
Se vogliamo limitare l'output ai soli utenti che usano bash come shell di login, possiamo fare così:
awk '
BEGIN { FS = ":" }
$7 == "/bin/bash" { print $1 }
' /etc/passwd
C'era una volta una città frenetica chiamata Cyberspace. Cyberspace era una metropoli digitale, con milioni di abitanti che si connettevano e disconnettevano ogni giorno. Per tenere traccia di tutti questi utenti, Cyberspace aveva un file speciale chiamato /etc/passwd.
Il file /etc/passwd era come un elenco telefonico per la città. Elencava ogni utente che aveva un account sul sistema, insieme ad alcune informazioni importanti su ciascun utente:
| n | campo |
|---|---|
| 1 | nome utente |
| 2 | password ("x" indica che la password effettiva è memorizzata altrove, per motivi di sicurezza) |
| 3 | UID, un ID numerico univoco dell'utente |
| 4 | GID, un ID numerico univoco del gruppo (tipicamente uguale all'UID) |
| 5 | informazioni sull'utente (tipicamente il nome completo dell'utente, ma può includere altre informazioni) |
| 6 | directory home |
| 7 | shell di login |
I campi sono separati da un carattere due punti. Questa è una voce tipica:
glennj:x:1010:1010:Glenn Jackman:/home/glennj:/usr/local/bin/fish
Il file era gestito da un team di amministratori di sistema, responsabili di creare nuovi account, aggiornare quelli esistenti e rimuovere quelli vecchi. Gli amministratori di sistema erano i custodi di Cyberspace. Facevano in modo che solo gli utenti autorizzati potessero accedere al sistema.
Un giorno, un nuovo amministratore di sistema di nome Alex fu assunto per unirsi al team. Alex era entusiasta di accettare il lavoro. Imparò rapidamente tutti i segreti del file /etc/passwd. Imparò come aggiungere nuovi utenti al sistema, come aggiornare le informazioni degli utenti e come rimuovere quelli vecchi.
Mentre Alex lavorava al file /etc/passwd, notò qualcosa di strano. Alcuni utenti avevano directory home strane o insolite. Alcuni utenti avevano la directory home impostata su /dev/null, mentre altri l'avevano impostata su percorsi strani che non esistevano.
Alex si rese conto che quegli utenti non erano persone reali, ma account falsi creati dagli hacker. Gli hacker avevano trovato il modo di sfruttare una vulnerabilità del sistema ed avevano creato questi account falsi per accedere a Cyberspace.
Alex sapeva che doveva agire. Usò awk per analizzare il file /etc/passwd e scrisse uno script per identificare tutti gli account falsi. Poi lavorò con il resto del team per rimuovere questi account e correggere la vulnerabilità che aveva permesso agli hacker di crearli.
Grazie all'uso di awk da parte di Alex, il team riuscì a identificare e rimuovere gli account falsi ed a rendere Cyberspace un posto più sicuro per tutti. Gli amministratori di sistema continuarono a gestire il file /etc/passwd, mantenendolo aggiornato e sicuro, ed assicurandosi che solo gli utenti autorizzati potessero accedere al sistema.
Ora tocca a te essere un amministratore di sistema come Alex.
Ecco un po' di sintassi AWK aggiuntiva che ti servirà per risolvere questo esercizio.
Gli operatori booleani sono simili a quelli di altri linguaggi:
| operazione | esempio |
|---|---|
| AND | expr1 && expr2 |
| OR | expr1 || expr2 |
| NOT | ! expr |
Chiamare una funzione ha una sintassi familiare:
function greet(name) {
print "Hello", name
}
BEGIN {
greet("Mary") # prints "Hello Mary"
}
Scrivi un programma awk che stampi il primo campo separato da due punti per ogni riga del file passwd.
Scrivi un comando awk che stampi il numero di riga di ogni record nel file di input. Stampa solo il numero di riga, non altre informazioni.
A Cyberspace, una directory home «valida» inizia con /home o /root.
Stampa i record del file di input con directory home non valide.
Stampa i record in cui la directory home è valida e la shell di login è bash.
Iscriviti a Exercism per imparare e padroneggiare AWK con 3 concetti92 esercizi e il mentoring di persone reali, tutto gratis.