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 3.2.25(1)-release
La mise à jour, version 2, du langage de script Bash classique ajoute les variables de type tableau, [106] 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.
[106] Chet Ramey a promit des tableaux associatifs (une fonctionnalité Perl intéressante) dans une future version de Bash. La version 3.2 n'en dispose toujours pas.