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].