Uno script che fa sempre la stessa cosa è poco utile: il bello arriva quando può decidere. In questo articolo vediamo i costrutti decisionali di Bash: il comando test, le parentesi quadre, if, elif, else e case, con gli script di esempio da provare.
Il comando test
Il comando test valuta una condizione e non stampa niente: restituisce soltanto un exit status. Zero significa vero, qualsiasi altro valore significa falso. L’exit status dell’ultimo comando lo leggiamo nella variabile speciale $?.
test 5 -eq 5
echo $?
L’output è questo, perché la condizione è vera:
0
Con una condizione falsa, invece:
test 5 -eq 6
echo $?
L’output è:
1
Gli operatori più usati sono questi.
- Stringhe: == uguali, != diverse, -n vera se la stringa non è vuota, -z vera se la stringa è vuota.
- Numeri: -eq uguale, -ne diverso, -gt maggiore, -ge maggiore o uguale, -lt minore, -le minore o uguale.
- File: -e vera se il file esiste.
Esiste anche la forma con le parentesi quadre, identica al comando test: la parentesi quadra aperta è proprio un comando, quindi servono gli spazi dopo la prima e prima dell’ultima.
[ 5 -eq 5 ]
echo $?
L’if
La struttura dell’if è questa: se la condizione è vera (exit status zero) si eseguono i comandi dopo then, altrimenti quelli dopo else. Si chiude con fi, cioè if scritto al contrario.
if [ 5 -eq 5 ]
then
echo "uguali"
fi
Stampa “uguali”. Ora uno script vero, che legge il primo argomento dalla riga di comando, cioè la variabile $1. Lo salviamo come if02.sh:
#!/bin/bash
if [ -n "$1" ]
then
echo $1
else
echo "non hai inserito nessun argomento"
fi
Si rende eseguibile e si prova con e senza argomento:
chmod +x if02.sh
./if02.sh ciao
./if02.sh
Nel primo caso stampa “ciao”, nel secondo “non hai inserito nessun argomento”. Le virgolette attorno a $1 sono importanti: se $1 è vuoto senza virgolette il test diventa [ -n ] e dà un risultato sbagliato.
Elif
Quando le alternative sono più di due si usa elif, “else if”. Lo script if03.sh confronta il numero passato come argomento con 5:
#!/bin/bash
if [ $1 -gt 5 ]
then
echo "maggiore di 5"
elif [ $1 -lt 5 ]
then
echo "minore di 5"
else
echo "uguale a 5"
fi
Proviamolo:
chmod +x if03.sh
./if03.sh 8
./if03.sh 2
./if03.sh 5
Se come argomento diamo qualcosa che non è un numero, per esempio una parola, Bash protesta con un errore del tipo “attesa espressione intera”: -gt e compagni lavorano solo sui numeri.
Nidificazione
Gli if si possono mettere uno dentro l’altro. Qui controlliamo prima che ci sia un argomento e poi lo confrontiamo:
#!/bin/bash
if [ -n "$1" ]
then
if [ $1 -gt 5 ]
then
echo "maggiore di 5"
else
echo "5 o meno"
fi
else
echo "manca l'argomento"
fi
Ogni if ha il suo fi, e il rientro serve a non perdersi.
Il case
Quando dobbiamo confrontare una stessa variabile con tanti valori, una catena di elif diventa pesante. Per questo c’è case. Ogni ramo termina con una parentesi tonda chiusa, l’asterisco fa da valore di default, e si chiude con esac, case al contrario. Lo script case.sh:
#!/bin/bash
case $1 in
a)
echo "hai scelto a"
;;
b)
echo "hai scelto b"
;;
*)
echo "scelta non valida"
;;
esac
Il doppio punto e virgola chiude ogni ramo. Proviamolo:
chmod +x case.sh
./case.sh a
./case.sh b
./case.sh z
Chiusura
Con test, if, elif e case abbiamo tutto quello che serve per far prendere decisioni ai nostri script.
Link e risorse
- il video su YouTube
- esempi e comandi della puntata su GitHub
- Manuale di Bash (man page) — in italiano
- Test e condizioni, BashGuide — test, [ ], [[ ]], if e case
- test, specifica POSIX — gli operatori del comando test
- Struttura di controllo — Wikipedia in italiano
