scripting Bash: i costrutti decisionali

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