Chapitre 35. Bash, version 2
La version actuelle de Bash, celle que vous
avez sur votre machine, est la version 2.XX.Y.
bash$ echo $BASH_VERSION
2.05.8(1)-release
|
Cette mise à jour du langage de script Bash classique ajoute les
variables de type tableau,
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 35-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'
echo $'Trois retours chariot \f \f \f'
echo $'10 retours chariot \n\n\n\n\n\n\n\n\n\n'
exit 0 |
Exemple 35-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 aurait été bien (sigh).
exit 0 |
Exemple 35-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" # color bands
B1723_loc=173 # where they are
B1723_inventory=78 # how many
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 methode 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 35-4. Utiliser des tableaux et autres astuces pour gérer quatre mains
aléatoires dans un jeu de cartes
#!/bin/bash
# A besoin d'être appelé avec #!/bin/bash2 sur les anciennes machines.
# Cartes:
# gère quatre mains d'un jeu de cartes.
UNPICKED=0
PICKED=1
DUPE_CARD=99
LOWER_LIMIT=0
UPPER_LIMIT=51
CARDS_IN_SUIT=13
CARDS=52
declare -a Deck
declare -a Suits
declare -a Cards
# It would have been easier and more intuitive
# with a single, 3-dimensional array.
# Perhaps a future version of Bash will support multidimensional arrays.
initialize_Deck ()
{
i=$LOWER_LIMIT
until [ "$i" -gt $UPPER_LIMIT ]
do
Deck[i]=$UNPICKED # Set each card of "Deck" as unpicked.
let "i += 1"
done
echo
}
initialize_Suits ()
{
Suits[0]=C #Clubs
Suits[1]=D #Diamonds
Suits[2]=H #Hearts
Suits[3]=S #Spades
}
initialize_Cards ()
{
Cards=(2 3 4 5 6 7 8 9 10 J Q K A)
# Alternate method of initializing an array.
}
pick_a_card ()
{
card_number=$RANDOM
let "card_number %= $CARDS"
if [ "${Deck[card_number]}" -eq $UNPICKED ]
then
Deck[card_number]=$PICKED
return $card_number
else
return $DUPE_CARD
fi
}
parse_card ()
{
number=$1
let "suit_number = number / CARDS_IN_SUIT"
suit=${Suits[suit_number]}
echo -n "$suit-"
let "card_no = number % CARDS_IN_SUIT"
Card=${Cards[card_no]}
printf %-4s $Card
# Print cards in neat columns.
}
seed_random () # Seed random number generator.
{
seed=`eval date +%s`
let "seed %= 32766"
RANDOM=$seed
}
deal_cards ()
{
echo
cards_picked=0
while [ "$cards_picked" -le $UPPER_LIMIT ]
do
pick_a_card
t=$?
if [ "$t" -ne $DUPE_CARD ]
then
parse_card $t
u=$cards_picked+1
# Change back to 1-based indexing (temporarily).
let "u %= $CARDS_IN_SUIT"
if [ "$u" -eq 0 ] # Nested if/then condition test.
then
echo
echo
fi
# Separate hands.
let "cards_picked += 1"
fi
done
echo
return 0
}
# Structured programming:
# entire program logic modularized in functions.
#================
seed_random
initialize_Deck
initialize_Suits
initialize_Cards
deal_cards
exit 0
#================
# Exercise 1:
# Add comments to thoroughly document this script.
# Exercise 2:
# Revise the script to print out each hand sorted in suits.
# You may add other bells and whistles if you like.
# Exercise 3:
# Simplify and streamline the logic of the script. |