| Guida avanzata di scripting Bash: Un'approfondita esplorazione dell'arte dello scripting di shell | ||
|---|---|---|
| Indietro | Avanti | |
Inizializzare o cambiare il valore di una variabile
Operatore di assegnamento multiuso, utilizzato sia per gli assegnamenti aritmetici che di stringhe.
var=27 categoria=minerali # Non sono consentiti spazi né prima né dopo l'"=".  | 
![]()  | Non bisogna confondere l'"=", operatore di assegnamento, con l'= operatore di verifica. 
 
  | 
più
meno
per
diviso
elevamento a potenza
# La versione 2.02 di Bash ha introdotto l'operatore di elevamento a potenza "**". let "z=5**3" echo "z = $z" # z = 125  | 
modulo, o mod (restituisce il resto di una divisione tra interi)
bash$ expr 5 % 3 2  | 
Questo operatore viene utilizzato, tra l'altro, per generare numeri in un determinato intervallo (vedi Esempio 9-25, Esempio 9-28) e per impaginare l'output dei programmi (vedi Esempio 26-15 e Esempio A-6). È anche utile per generare numeri primi, (vedi Esempio A-16). Modulo si trova sorprendentemente spesso in diverse formule matematiche.
Esempio 8-1. Massimo comun divisore
#!/bin/bash
# gcd.sh: massimo comun divisore
#         Uso dell'algoritmo di Euclide
#  Il "massimo comun divisore" (MCD) di due interi è l'intero 
#+ più grande che divide esattamente entrambi.
#  L'algoritmo di Euclide si basa su divisioni successive.
#  Ad ogni passaggio,
#+ dividendo <---  divisore
#+ divisore  <---  resto
#+ finché resto = 0.
#+ Nell'ultimo passaggio MCD = dividendo.
#
#  Per un'eccellente disamina dell'algoritmo di Euclide, vedi
#+ al sito di Jim Loy, http://www.jimloy.com/number/euclids.htm.
# ----------------------------------------------------------
# Verifica degli argomenti
ARG=2
E_ERR_ARG=65
if [ $# -ne "$ARG" ]
then
  echo "Utilizzo: `basename $0` primo-numero secondo-numero"
  exit $E_ERR_ARG
fi
# ----------------------------------------------------------
mcd ()
{
                                 
  dividendo=$1                 #   Assegnamento arbitrario.     
  divisore=$2                  #!  Non ha importanza quale dei due è maggiore.
                               #   Perché?
  resto=1                      #   Se la variabile usata in un ciclo non è
                               #+  inizializzata, il risultato è un errore
                               #+  al primo passaggio nel ciclo.
  until [ "$resto" -eq 0 ]
  do
    let "resto = $dividendo % $divisore"
    dividendo=$divisore        # Ora viene ripetuto con 2 numeri più piccoli.
    divisore=$resto
  done                         # Algoritmo di Euclide
}                              # L'ultimo $dividendo è il MCD.
mcd $1 $2
echo; echo "MCD di $1 e $2 = $dividendo"; echo
# Esercizio :
# --------
#  Verificate gli argomenti da riga di comando per essere certi che siano 
#+ degli interi, se non lo fossero uscite dallo script con un adeguato 
#+ messaggio d'errore.
exit 0 | 
"più-uguale" (incrementa una variabile con una costante
let "var += 5" come risultato
	      var è stata incrementata di
	      5.
"meno-uguale" (decrementa una variabile di una costante)
"per-uguale" (moltiplica una variabile per una costante)
let "var *= 4" come risultato 
	      var è stata moltiplicata per
	    4.
"diviso-uguale" (divide una variabile per una costante)
"modulo-uguale" (resto della divisione di una variabile per una costante)
Gli operatori aritmetici si trovano spesso in espressioni con expr o let.
Esempio 8-2. Utilizzo delle operazioni aritmetiche
#!/bin/bash # Contare fino a 11 in 10 modi diversi. n=1; echo -n "$n " let "n = $n + 1" # Va bene anche let "n = n + 1". echo -n "$n " : $((n = $n + 1)) # I ":" sono necessari perché altrimenti Bash tenta #+ di interpretare "$((n = $n + 1))" come un comando. echo -n "$n " (( n = n + 1 )) # Alternativa più semplice del metodo precedente. # Grazie a David Lombard per la precisazione. echo -n "$n " n=$(($n + 1)) echo -n "$n " : $[ n = $n + 1 ] # I ":" sono necessari perché altrimenti Bash tenta #+ di interpretare "$[ n = $n + 1 ]" come un comando. # Funziona anche se "n" fosse inizializzata come stringa. echo -n "$n " n=$[ $n + 1 ] # Funziona anche se "n" fosse inizializzata come stringa. #* Evitate questo costrutto perché è obsoleto e non portabile. # Grazie, Stephane Chazelas. echo -n "$n " # Ora con gli operatori di incremento in stile C. # Grazie a Frank Wang per averlo segnalato. let "n++" # anche con let "++n". echo -n "$n " (( n++ )) # anche con (( ++n ). echo -n "$n " : $(( n++ )) # anche con : $(( ++n )). echo -n "$n " : $[ n++ ] # e anche : $[ ++n ]] echo -n "$n " echo exit 0  | 
![]()  | In Bash, attualmente, le variabili intere sono del tipo signed long (32-bit) comprese nell'intervallo da -2147483648 a 2147483647. Un'operazione comprendente una variabile con un valore al di fuori di questi limiti dà un risultato sbagliato. 
 
 Dalla versione 2.05b, Bash supporta gli interi di 64 bit.  | 
![]()  | Bash non contempla l'aritmetica in virgola mobile. Considera i numeri che contengono il punto decimale come stringhe. 
 
 Si utilizzi bc negli script in cui sono necessari i calcoli in virgola mobile, oppure le librerie di funzioni matematiche.  | 
Operatori bitwise. Gli operatori bitwise compaiono raramente negli script di shell. L'uso principale sembra essere quello di manipolare e verificare i valori letti dalle porte o dai socket. "Lo scorrimento di bit" è più importante nei linguaggi compilati, come il C e il C++, che sono abbastanza veloci per consentirne un uso proficuo.
scorrimento a sinistra (moltiplicazione per 2 per ogni posizione spostata)
"scorrimento a sinistra-uguale"
let "var <<= 2" come risultato 
	     i bit di var sono stati spostati di
	    2 posizioni verso sinistra (moltiplicazione 
	    per 4)
scorrimento a destra (divisione per 2 per ogni posizione spostata)
"scorrimento a destra-uguale" (inverso di <<=)
AND bitwise
"AND bitwise-uguale"
OR bitwise
"OR bitwise-uguale"
complemento bitwise
NOT bitwise
XOR bitwise
"XOR bitwise-uguale"
and (logico)
if [ $condizione1 ] && [ $condizione2 ] # Uguale a: if [ $condizione1 -a $condizione2 ] # Restituisce vero se entrambe, condizione1 e condizione2, sono vere... if [[ $condizione1 && $condizione2 ]] # Funziona anche così. # Notate che l'operatore && non è consentito nel costrutto [ ... ].  | 
![]()  | && può essere utilizzato, secondo il contesto, in una lista and per concatenare dei comandi.  | 
or (logico)
if [ $condizione1 ] || [ $condizione2 ] # Uguale a: if [ $condizione1 -o $condizione2 ] # Restituisce vero se è vera o condizione1 o condizione2 ... if [[ $condizione1 || $condizione2 ]] # Funziona anche così. # Notate che l'operatore || non è consentito nel costrutto [ ... ].  | 
![]()  | Bash verifica l'exit status di ogni enunciato collegato con un operatore logico.  | 
Esempio 8-3. Condizioni di verifica composte utilizzando && e ||
#!/bin/bash
a=24
b=47
if [ "$a" -eq 24 ] && [ "$b" -eq 47 ]
then
  echo "Verifica nr.1 eseguita con successo."
else
  echo "Verifica nr.1 fallita."
fi
# ERRORE:  if [ "$a" -eq 24 && "$b" -eq 47 ]
#+         cerca di eseguire  ' [ "$a" -eq 24 '
#+         e fallisce nella ricerca di corrispondenza di ']'.
#
#  Nota:   if [[ $a -eq 24 && $b -eq 24 ]]   funziona
#  La verifica if con le doppie parentesi quadre è più flessibile
#+ della versione con le paretesi quadre singole.
#    ("&&" ha un significato diverso nella riga 17 di quello della riga 6.).
#    Grazie a Stephane Chazelas per averlo evidenziato.
if [ "$a" -eq 98 ] || [ "$b" -eq 47 ]
then
  echo "Verifica nr.2 eseguita con successo."
else
  echo "Verifica nr.2 fallita."
fi
#  Le opzioni -a e -o offrono
#+ una condizione di verifica composta alternativa.
#  Grazie a Patrick Callahan per la precisazione.
if [ "$a" -eq 24 -a "$b" -eq 47 ]
then
  echo "Verifica nr.3 eseguita con successo."
else
  echo "Verifica nr.3 fallita."
fi
if [ "$a" -eq 98 -o "$b" -eq 47 ]
then
  echo "Verifica nr.4 eseguita con successo."
else
  echo "Verifica nr.4 fallita."
fi
a=rinoceronte
b=coccodrillo
if [ "$a" = rinoceronte ] && [ "$b" = coccodrillo ]
then
  echo "Verifica nr.5 eseguita con successo."
else
  echo "Verifica nr.5 fallita."
fi
exit 0 | 
Gli operatori && e || vengono utilizzati anche nel contesto matematico.
bash$ echo $(( 1 && 2 )) $((3 && 0)) $((4 || 0)) $((0 || 0)) 1 0 1 0  | 
operatore virgola
L'operatore virgola concatena due o più operazioni aritmetiche. Vengono valutate tutte le operazioni (con possibili effetti collaterali), ma viene restituita solo l'ultima.
let "t1 = ((5 + 3, 7 - 1, 15 - 4))" echo "t1 = $t1" # t1 = 11 let "t2 = ((a = 9, 15 / 3))" # Imposta "a" e calcola "t2" echo "t2 = $t2 a = $a" # t2 = 5 a = 9  | 
L'operatore virgola viene impiegato principalmente nei cicli for. Vedi Esempio 10-12.