La versione corrente di Bash, quella
che viene eseguita sulla vostra macchina, attualmente è la 2.xx.y o la 3.xx.y.
bash$ echo $BASH_VERSION
2.05.b.0(1)-release
|
La versione 2, aggiornamento del classico linguaggio di scripting
di Bash, ha aggiunto gli array,
l'espansione di stringa e di parametro, e un metodo
migliore per le referenziazioni indirette a variabili.
Esempio 34-1. Espansione di stringa
#!/bin/bash
# Espansione di stringa.
# Introdotta con la versione 2 di Bash.
# Le stringhe nella forma $'xxx'
#+ consentono l'interpretazione delle sequenze di escape standard.
echo $'Tre segnali acustici \a \a \a'
# Su alcuni terminali potrebbe venir eseguito un solo segnale acustico.
echo $'Tre form feed \f \f \f'
echo $'10 ritorni a capo \n\n\n\n\n\n\n\n\n\n'
echo $'\102\141\163\150' # Bash
# Valori ottali di ciascun carattere.
exit 0 |
Esempio 34-2. Referenziazioni indirette a variabili - una forma nuova
#!/bin/bash
# Referenziazione indiretta a variabile.
# Possiede alcuni degli attributi delle referenziazioni del C++.
a=lettera_alfabetica
lettera_alfabetica=z
echo "a = $a" # Referenziazione diretta.
echo "Ora a = ${!a}" # Referenziazione indiretta.
# La notazione ${!variabile} è di molto superiore alla vecchia
#+ "eval var1=\$$var2"
echo
t=cella_3
cella_3=24
echo "t = ${!t}" # t = 24
cella_3=387
echo "Il valore di t è cambiato in ${!t}" # 387
# È utile per il riferimento ai membri di un array o di una tabella,
#+ o per simulare un array multidimensionale.
# Un'opzione d'indicizzazione sarebbe stata più gradita. Sigh.
exit 0 |
Esempio 34-3. Applicazione di un semplice database, con l'utilizzo
della referenziazione indiretta
#!/bin/bash
# resistor-inventory.sh
# Applicazione di un semplice database che utilizza la referenziazione
#+ indiretta alle variabili.
# ============================================================== #
# Dati
B1723_valore=470 # Ohm
B1723_potenzadissip=.25 # Watt
B1723_colori="giallo-viola-marrone" # Colori di codice
B1723_loc=173 # Posizione
B1723_inventario=78 # Quantità
B1724_valore=1000
B1724_potenzadissip=.25
B1724_colori="marrone-nero-rosso"
B1724_loc=24N
B1724_inventario=243
B1725_valore=10000
B1725_potenzadissip=.25
B1725_colori="marrone-nero-arancione"
B1725_loc=24N
B1725_inventario=89
# ============================================================== #
echo
PS3='Inserisci il numero di catalogo: '
echo
select numero_catalogo in "B1723" "B1724" "B1725"
do
Inv=${numero_catalogo}_inventario
Val=${numero_catalogo}_valore
Pdissip=${numero_catalogo}_potenzadissip
Loc=${numero_catalogo}_loc
Codcol=${numero_catalogo}_colori
echo
echo "Numero di catalogo $numero_catalogo:"
echo "In magazzino ci sono ${!Inv} resistori da\
[${!Val} ohm / ${!Pdissip} watt]."
echo "Si trovano nel contenitore nr. ${!Loc}."
echo "Il loro colore di codice è \"${!Codcol}\"."
break
done
echo; echo
# Esercizi:
# --------
# 1) Riscrivete lo script in modo che legga i dati da un file esterno.
# 2) Riscrivete lo script utilizzando gli array, al posto della
#+ referenziazione indiretta a variabile.
# Quale, tra i due, è il metodo più diretto e intuitivo?
# Nota:
# -----
# Gli script di shell non sono appropriati per le applicazioni di database,
#+ tranne quelle più semplici. Anche in questi casi, però,
#+ bisogna ricorrere ad espedienti e trucchi vari.
# È molto meglio utilizzare un linguaggio che abbia un
#+ supporto nativo per le strutture, come C++ o Java (o anche Perl).
exit 0 |
Esempio 34-4. Utilizzo degli array e di vari altri espedienti per
simulare la distribuzione casuale di un mazzo di carte a 4
giocatori
#!/bin/bash
# Carte:
# Distribuzione di un mazzo di carte a quattro giocatori.
NONDISTRIBUITA=0
DISTRIBUITA=1
GIÀ_ASSEGNATA=99
LIMITE_INFERIORE=0
LIMITE_SUPERIORE=51
CARTE_PER_SEME=13
CARTE=52
declare -a Mazzo
declare -a Semi
declare -a Carte
# Sarebbe stato più semplice ed intuitivo
#+ con un unico array tridimensionale.
# Forse una futura versione di Bash supporterà gli array multidimensionali.
Inizializza_Mazzo ()
{
i=$LIMITE_INFERIORE
until [ "$i" -gt $LIMITE_SUPERIORE ]
do
Mazzo[i]=$NONDISTRIBUITA # Imposta ogni carta del "Mazzo" come non
#+ distribuita.
let "i += 1"
done
echo
}
Inizializza_Semi ()
{
Semi[0]=F #Fiori
Semi[1]=Q #Quadri
Semi[2]=C #Cuori
Semi[3]=P #Picche
}
Inizializza_Carte ()
{
Carte=(2 3 4 5 6 7 8 9 10 J Q K A)
# Metodo alternativo di inizializzazione di array.
}
Sceglie_Carta ()
{
numero_carta=$RANDOM
let "numero_carta %= $CARTE"
if [ "${Mazzo[numero_carta]}" -eq $NONDISTRIBUITA ]
then
Mazzo[numero_carta]=$DISTRIBUITA
return $numero_carta
else
return $GIÀ_ASSEGNATA
fi
}
Determina_Carta ()
{
numero=$1
let "numero_seme = numero / CARTE_PER_SEME"
seme=${Semi[numero_seme]}
echo -n "$seme-"
let "nr_carta = numero % CARTE_PER_SEME"
Carta=${Carte[nr_carta]}
printf %-4s $Carta
# Visualizza le carte ben ordinate per colonne.
}
Seme_Casuale () # Imposta il seme del generatore di numeri casuali.
{ # Cosa succederebbe se questo non venisse fatto?
Seme=`eval date +%s`
let "Seme %= 32766"
RANDOM=$Seme
# Quali sono gli altri metodi per impostare il seme
#+ del generatore di numeri casuali?
}
Da_Carte ()
{
echo
carte_date=0
while [ "$carte_date" -le $LIMITE_SUPERIORE ]
do
Sceglie_Carta
t=$?
if [ "$t" -ne $GIÀ_ASSEGNATA ]
then
Determina_Carta $t
u=$carte_date+1
# Ritorniamo all'indicizzazione in base 1 (temporaneamente). Perché?
let "u %= $CARTE_PER_SEME"
if [ "$u" -eq 0 ] # Costrutto condizionale if/then annidato.
then
echo
echo
fi
# Separa i giocatori.
let "carte_date += 1"
fi
done
echo
return 0
}
# Programmazione strutturata:
# l'intero programma è stato "modularizzato" per mezzo delle Funzioni.
#================
Seme_Casuale
Inizializza_Mazzo
Inizializza_Semi
Inizializza_Carte
Da_Carte
#================
exit 0
# Esercizio 1:
# Aggiungete commenti che spieghino completamente lo script.
# Esercizio 2:
# Aggiungete una routine (funzione) per visualizzare la distribuzione ordinata
#+ per seme.
# Potete aggiungere altri fronzoli, si vi aggrada.
# Esercizio 3:
# Semplificate e raffinate la logica dello script. |