Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Costrutti condizionali: if e case

Imparare a conoscere i costrutti condizionali if e case, e come utilizzarli nella scrittura di uno script di Shell.
Imparare a conoscere i costrutti condizionali if e case, e come utilizzarli nella scrittura di uno script di Shell.
Link copiato negli appunti

Adesso che conosciamo diversi modi di specificare condizioni e manipolare variabili è giunto il momento di introdurre i costrutti condizionali più classici, che ci permetteranno di comporre script sempre più complessi.

Bash include il costrutto tipico di ogni linguaggio di programmazione, ovvero l'if-then-else. L'if in Bash è un comando composto che valuta il risultato di un test o comando ($?) e si dirama in base al suo valore, vero (0) o falso (1). Viene seguito da una clausola then contenente la lista dei comandi da eseguire nel caso in cui il test (o comando) ritorni 0. Ad essa possono seguire una o più clausole opzionali elif, ognuna associata ad un test addizionale e seguita a sua volta da un'ulteriore then, cui segue una lista di comandi. Infine può essere presente un'opzionale clausola else, seguita da una lista di comandi che dovranno essere eseguiti nel caso in cui né il test originale né ciascuno di quelli utilizzati nelle clausole elif siano veri. Il comando termina quindi con il comando fi per segnalare la fine del costrutto.

Vediamo di chiarire come vengono specificate le condizioni e i comandi associati ai diversi risultati, con l'aiuto di alcuni esempi. Utilizzeremo la sintassi più flessibile del comando test, ma è possibile specificare le condizioni anche utilizzando la sintassi basata sullo standard POSIX, come abbiamo discusso nella lezione precedente.

Iniziamo con un semplice test su file; lo script che segue controlla l'esistenza del file originale.txt e - nel caso di risposta affermativa - lo copia con il nome di copia.txt utilizzando il comando cp e mostrando un messaggio di successo.

#!/bin/bash
if [[ -e originale.txt ]] ; then
  cp originale.txt copia.txt
  echo "Copia riuscita."
fi

L'indentazione dei due comandi all'interno dell'if non è obbligatoria, ma agevola la leggibilità del codice, quindi è sempre consigliabile.

L'esempio specificato utilizza la condizione -e che risulta vera se il file che la segue esiste; nel caso in cui ciò si verifichi, i due comandi che seguono la clausola then vengono eseguiti, altrimenti il blocco if viene ignorato. Aggiungendo la clausola else al precedente esempio, è possibile offrire un feedback testuale anche nel caso in cui il file non esista, in questo modo:

#!/bin/bash
if [[ -e originale.txt ]] ; then
  cp originale.txt copia.txt
  echo "Copia riuscita."
else
  echo "Il file non esiste."
fi

Poiché il costrutto if costituisce anch'esso un comando, è possibile anche utilizzarlo all'interno di un altro if di livello superiore; vediamo un esempio.

#!/bin/bash
if [[ -e originale.txt ]] ; then
  cp originale.txt copia.txt
  echo "Copia riuscita."
else
  if [[ -e nuovo.txt ]] ; then
    echo "originale.txt non esiste, ma nuovo.txt sì."
    cp nuovo.txt copia.txt
    echo "Copia riuscita."
  else
    echo "Non esiste né originale.txt né nuovo.txt."
  fi
fi

La logica dei test dell'esempio appena descritto fa sì che, nel caso in cui il file originale.txt esista, le prime due righe vengano eseguite, altrimenti vengono eseguiti i comandi contenuti all'interno della prima clausola else. Il comando in essa contenuto è un ulteriore if, che controlla l'esistenza del file nuovo.txt, copiandolo in caso affermativo o stampando un messaggio altrimenti.

Per rendere il codice precedente più leggibile e strutturato, si può introdurre una clausola elif, rendendo superflua la presenza di un doppio if, in questo modo:

#!/bin/bash
if [[ -e originale.txt ]] ; then
  cp originale.txt copia.txt
  echo "Copia riuscita."
elif [[ -e nuovo.txt ]] ; then
  echo "originale.txt non esiste, ma nuovo.txt sì."
  cp nuovo.txt copia.txt
  echo "Copia riuscita."
else
  echo "Non esiste né originale.txt né nuovo.txt."
fi

Ci sono casi in cui la presenza di troppe clausule elif limita la leggibilità del codice, ad esempio quando vogliamo leggere un input non strutturato fornito dall'utente e prendere una decisione conseguente, in genere per ogni opzione fornita si dovrà inserire una clausola elif con una condizione del tutto identica alla precedente, cambiando solamente il valore dell'espressione da identificare. È in casi come questi che è molto utile utilizzare il costrutto case, che permette una più agile definizione di condizioni sul valore di una variabile, come si nota dall'esempio seguente:

#!/bin/bash
echo "Inserisci un numero da 1 a 10: "
read opt
case $opt in
1)
  echo "Hai inserito uno!" ;;
2)
  echo "Hai inserito due!" ;;
3)
  echo "Hai inserito tre!" ;;
4)
  echo "Hai inserito quattro!" ;;
5)
  echo "Hai inserito cinque!" ;;
6)
  echo "Hai inserito sei!" ;;
7)
  echo "Hai inserito sette!" ;;
8)
  echo "Hai inserito otto!" ;;
9)
  echo "Hai inserito nove!" ;;
10)
  echo "Hai inserito dieci!" ;;
*)
  echo "Non hai inserito un numero da 1 a 10..." ;;
esac

La sintassi è molto intuitiva e il risultato molto leggibile: viene letto e memorizzato l'input dell'utente nella variabile $opt per essere poi usata come argomento del costrutto case. Ogni opzione seguita da una parentesi chiusa ) determina il valore che deve assumere la variabile perché i comandi che la seguono - terminati da ;; - vengano eseguiti. Nel caso in cui la variabile non contenga nessuno dei valori specificati, il blocco case viene ignorato, e per questo è sempre utile terminarlo con il pattern *, che determina i comandi da eseguire nel caso in cui nessuna delle precedenti opzioni sia stata identificata come contenuta nella variabile.

Per concludere, vale la pena evidenziare che le opzioni specificate in una clausola case possono essere espresse come pattern, utilizzando la sintassi specificata da Bash. Chi volesse approfondire questo aspetto può fare riferimento alla pagina di aiuto, digitando il comando man bash.

Ti consigliamo anche