Bash offre deux moyens pour obtenir la valeur d'une variable v1 dont le nom est accessible via une autre variable var : l'indirection par substitution et les variables nameref. Ces mécanismes, appelés indirections, permettent d'accéder de manière indirecte et pa conséquent de façon plus souple, à la valeur d'un deuxième objet.
On utilise la syntaxe de substitution suivante : ${!var}.
$ var=v1 $ v1=un $ $ echo ${!var} un $
La variable var a pour valeur la chaine v1. Celle-ci correspond au nom d'une deuxième variable ayant pour valeur la chaine un. La syntaxe ${!var} permet d'accéder indirectement à la valeur de la variable v1.
Le fichier shell indir illustre la souplesse des indirections en montrant comment il est possible de créer « à la volée » le nom de la variable qui contient l’information souhaitée.
#!/bin/bash # @(#) indir agePierre=10 ageJean=20 read -p "Quel age (Pierre ou Jean) voulez-vous connaitre ? " prenom rep=age$prenom # construction du nom de la variable echo ${!rep}
Deux variables agePierre et ageJean contiennent respectivement l’âge des personnes Pierre et Jean. Le programme demande à l’utilisateur de saisir le prénom dont il souhaite connaître l’âge, construit le nom de la variable contenant l’âge demandé puis affiche ce dernier.
$ indir Quel age (Pierre ou Jean) voulez-vous connaitre ? Pierre 10 $ $ indir Quel age (Pierre ou Jean) voulez-vous connaitre ? Jean 20 $
Ce mécanisme s’applique également aux deux autres types de paramètres : les paramètres de position et les paramètres spéciaux.
$ x=un $ b=deux $ c=trois $ $ set x b c => $1, $2 et $3 ont respectivement pour valeur les chaînes $ => "x", "b", "c" $ echo $2 b $ $ echo ${!2} => la valeur de $2 est la chaîne "b" qui est le nom d’une variable deux => contenant la valeur "deux" $ $ echo ${!3} trois $ $ echo ${!#} => la valeur de $# est 3 et la valeur de $3 est la chaîne "c" c $
Remarque :
il ne faut pas confondre deux syntaxes très proches fournies par bash mais qui correspondent à deux mécanismes totalement différents : ${!param} et ${!var*}
La première syntaxe sera interprétée par le shell comme une indirection, tandis que la deuxième sera remplacée par les noms de variables qui commencent par var.
$ A=alpha $ x=beta $ Age=20 $ $ echo ${!A*} => ${!A*} sera remplacée par les noms de A Age => variables qui commencent par A $
Une variable nameref var contient une référence à une autre variable v.
Pour définir une variable nameref on peut utiliser la syntaxe suivante : declare -n var[=v].
$ declare -n var1=v2 $ declare -p var1 declare -n var1="v2" $ $ v2=bonjour $ $ echo $var1 bonjour => valeur de la variable v2 $ $ v2=hello $ $ echo $var1 hello $
Contrairement aux indirections par substitution, après initialisation d'une variable nameref, on ne peut modifier la référence qu'elle contient (à moins de redéfinir la variable nameref).
$ v3="au revoir" $ var1=v3 $ echo $var1 v3 => affichage du nom de la variable (v3) et non de sa valeur (au revoir) $ $ declare -n var1=v3 => redéfinition de var1 $ echo $var1 au revoir => affichage correct de la valeur de la variable v3 $
Le mécanisme nameref est généralement utilisé par une fonction pour modifier la valeur d'une variable qui lui est extérieure et qui lui a été transmise en argument [cf. Chapitre 14, Fonctions shell].