La version actuelle de Bash, celle que vous avez sur votre machine, est la version 2.xx.y ou 3.xx.y.
bash$ echo $BASH_VERSION
2.05.b.0(1)-release
La mise à jour, version 2, du langage de script Bash classique ajoute les variables de type tableau, [92] l'expansion de chaînes de caractères et de paramètres, et une meilleure méthode pour les références de variables indirectes, parmi toutes les fonctionnalités.
Exemple 34.1. Expansion de chaîne de caractères
#!/bin/bash
# Expansion de chaînes de caractères.
# Introduit avec la version 2 de Bash.
# Les chaînes de caractères de la forme $'xxx' ont les caractères d'échappement
# standard interprétés.
echo $'Trois cloches sonnant à la fois \a \a \a'
# Pourrait sonner seulement une fois sur certains terminaux.
echo $'Trois retours chariot \f \f \f'
echo $'10 retours chariot \n\n\n\n\n\n\n\n\n\n'
echo $'\102\141\163\150' # Bash
# Équivalent en octal des caractères.
exit 0
Exemple 34.2. Références de variables indirectes - la nouvelle façon
#!/bin/bash
# Référencement de variables indirectes.
# Ceci a quelques-uns des attributs du C++.
a=lettre_de_l_alphabet
lettre_de_l_alphabet=z
echo "a = $a" # Référence directe.
echo "Maintenant a = ${!a}" # Référence indirecte.
# La notation ${!variable} est bien supérieure à l'ancien "eval var1=\$$var2"
echo
t=cellule_table_3
cellule_table_3=24
echo "t = ${!t}" # t = 24
cellule_table_3=387
echo "La valeur de t a changé en ${!t}" # 387
# Ceci est utile pour référencer les membres d'un tableau ou d'une table,
# ou pour simuler un tableau multi-dimensionnel.
# Une option d'indexage (analogue à un pointeur arithmétique) aurait été bien.
#+ Sigh.
exit 0
Exemple 34.3. Simple application de base de données, utilisant les références de variables indirectes
#!/bin/bash
# resistor-inventory.sh
# Simple base de données utilisant le référencement indirecte de variables.
# ============================================================== #
# Données
B1723_value=470 # Ohms
B1723_powerdissip=.25 # Watts
B1723_colorcode="yellow-violet-brown" # Bandes de couleurs
B1723_loc=173 # Où elles sont
B1723_inventory=78 # Combien
B1724_value=1000
B1724_powerdissip=.25
B1724_colorcode="brown-black-red"
B1724_loc=24N
B1724_inventory=243
B1725_value=10000
B1725_powerdissip=.25
B1725_colorcode="brown-black-orange"
B1725_loc=24N
B1725_inventory=89
# ============================================================== #
echo
PS3='Entrez le numéro du catalogue : '
echo
select numero_catalogue in "B1723" "B1724" "B1725"
do
Inv=${numero_catalogue}_inventory
Val=${numero_catalogue}_value
Pdissip=${numero_catalogue}_powerdissip
Loc=${numero_catalogue}_loc
Ccode=${numero_catalogue}_colorcode
echo
echo "Catalogue numéro $numero_catalogue :"
echo "Il existe ${!Inv} résistances de [${!Val} ohm / ${!Pdissip} watt] en stock."
echo "Elles sont situées dans bin # ${!Loc}."
echo "Leur code couleur est \"${!Ccode}\"."
break
done
echo; echo
# Exercice :
# ---------
# Réécrire ce script en utilisant des tableaux, plutôt qu'en utilisant le
#+ référencement indirecte des variables.
# Quelle méthode est plus logique et intuitive ?
# Notes :
# ------
# Les scripts shells sont inappropriés pour tout, sauf des applications simples
#+ de base de données, et, même là, cela implique des astuces.
# Il est bien mieux d'utiliser un langage supportant nativement les structures
#+ de données, tels que C++ ou Java (voire même Perl).
exit 0
Exemple 34.4. Utiliser des tableaux et autres astuces pour gérer quatre mains aléatoires dans un jeu de cartes
#!/bin/bash
# Cartes :
# Gère quatre mains d'un jeu de cartes.
NON_RECUPERE=0
RECUPERE=1
DUPE_CARD=99
LIMITE_BASSE=0
LIMITE_HAUTE=51
CARTES_DANS_SUITE=13
CARTES=52
declare -a Jeu
declare -a Suites
declare -a Cartes
# Le script aurait été plus simple à implémenter et plus intuitif
#+ avec un seul tableau à trois dimensions.
# Peut-être qu'une future version de Bash gèrera des tableaux multi-dimensionnels.
initialise_Jeu ()
{
i=$LIMITE_BASSE
until [ "$i" -gt $LIMITE_HAUTE ]
do
Jeu[i]=$NON_RECUPERE # Initialise chaque carte d'un "Jeu" comme non récupérée.
let "i += 1"
done
echo
}
initialise_Suites ()
{
Suites[0]=C #Carreaux
Suites[1]=D #Piques
Suites[2]=H #Coeurs
Suites[3]=S #Trèfles
}
initialise_Cartes ()
{
Cartes=(2 3 4 5 6 7 8 9 10 J Q K A)
# Autre méthode pour initialiser un tableau.
}
recupere_une_carte ()
{
numero_carte=$ALEATOIRE
let "numero_carte %= $CARTES"
if [ "${Jeu[numero_carte]}" -eq $NON_RECUPERE ]
then
Jeu[numero_carte]=$RECUPERE
return $numero_carte
else
return $DUPE_CARD
fi
}
analyse_carte ()
{
nombre=$1
let "suit_nombre = nombre / CARTES_DANS_SUITE"
suite=${Suites[suit_nombre]}
echo -n "$suit-"
let "no_carte = nombre % CARTES_DANS_SUITE"
Carte=${Cartes[no_carte]}
printf %-4s $Carte
# Affiche proprement les cartes.
}
recherche_nombre_aleatoire () # Générateur de nombres aléatoires.
{ # Que se passe-t'il si vous ne faites pas cela ?
recherche=`eval date +%s`
let "recherche %= 32766"
ALEATOIRE=$recherche
# Quelles sont les autres méthodes de génération de nombres aléatoires ?
}
gere_cartes ()
{
echo
cartes_recuperees=0
while [ "$cartes_recuperees" -le $LIMITE_HAUTE ]
do
recupere_une_carte
t=$?
if [ "$t" -ne $DUPE_CARD ]
then
analyse_carte $t
u=$cartes_recuperees+1
# Retour à un indexage simple (temporairement). Pourquoi ?
let "u %= $CARTES_DANS_SUITE"
if [ "$u" -eq 0 ] # Condition if/then imbriquée.
then
echo
echo
fi
# Mains séparées.
let "cartes_recuperees += 1"
fi
done
echo
return 0
}
# Programmation structurée :
# La logique entière du programme est modularisée en fonctions.
#================
recherche_nombre_aleatoire
initialise_Jeu
initialise_Suites
initialise_Cartes
gere_cartes
#================
exit 0
# Exercice 1 :
# Ajouter des commentaires détaillées de ce script.
# Exercice 2 :
# Ajouter une routine (fonction) pour afficher chaque main triée par suite.
# Vous pouvez ajouter d'autres fonctionnalités suivant vos souhaits.
# Exercice 3 :
# Simplifier et améliorer la logique du script.
[92] Chet Ramey a promit des tableaux associatifs (une fonctionnalité Perl) dans une future version de Bash. La version 3 n'en dispose toujours pas.