Les tableaux associatifs semblent être locaux par défaut lorsqu'ils sont déclarés dans un corps de fonction, où ils devraient être globaux. Le code suivant
#!/bin/bash
f() {
declare -A map
map[x]=a
map[y]=b
}
f
echo x: ${map[x]} y: ${map[y]}
produit la sortie:
x: y:
alors que ce
#!/bin/bash
declare -A map
f() {
map[x]=a
map[y]=b
}
f
echo x: ${map[x]} y: ${map[y]}
produit la sortie:
x: a y: b
Est-il possible de déclarer un tableau associatif global au sein d'une fonction? Ou quelle solution de contournement peut être utilisée?
De: Greg Wooledge
Envoyé: mar, 23 août 2011 06:53:27 -0700
Objet: Re: YAQAGV (Encore une question sur les variables globales)bash 4.2 ajoute "declare -g" pour créer des variables globales à partir d'une fonction .
Merci Greg! Cependant, Squeeze Debian a toujours Bash 4.1.5
Vous avez déjà répondu à votre propre question avec declare -g. La solution de contournement sur les versions de bash <4.2 consiste à déclarer le tableau en dehors de la fonction.
f() {
map[y] = foo
}
declare -A map
foo
echo "${map[y]}"
Très bien, 4.2 ajoute "declare -g" mais c'est un buggy pour les tableaux associatifs, donc il ne répond pas (encore) à la question. Voici mon rapport de bogue et la confirmation de Chet qu'un correctif est prévu pour la prochaine version.
http://lists.gnu.org/archive/html/bug-bash/2013-09/msg00025.html
Mais j'ai trouvé par hasard une solution de contournement, au lieu de déclarer le tableau et de lui affecter une valeur initiale en même temps, commencez par déclarer le tableau, puis effectuez l'affectation. C'est-à-dire, ne faites pas ceci:
declare -gA a=([x]=1 [y]=2)
mais ceci à la place:
declare -gA a; a=([x]=1 [y]=2)
Pour ceux qui sont coincés avec la version <4.2 de Bash et qui ne sont pas à l'aise avec les solutions de contournement proposées, je partage mon implémentation personnalisée de tableaux associatifs globaux. Il n’a pas toute la puissance des tableaux associatifs bash et vous devez faire attention aux caractères spéciaux dans l’index de tableau, mais le travail doit être fait.
get_array(){
local arr_name="$1"
local arr_key="$2"
arr_namekey_var="ASSOCARRAY__${arr_name}__${arr_key}"
echo "${!arr_namekey_var:=}"
}
set_array(){
local arr_name="$1"
local arr_key="$2"
local arr_value="$3"
arr_namekey_var="ASSOCARRAY__${arr_name}__${arr_key}"
if [[ -z "${arr_value}" ]]; then
eval ${arr_namekey_var}=
else
printf -v "${arr_namekey_var}" "${arr_value}"
fi
}
Quelques notes:
__
en tant que séparateur peut être piraté par une utilisation malveillante ou négligente - pour être sûr, n'utilisez que des valeurs de soulignement simple dans le nom et la clé du tableau, en plus des valeurs alphanumériques. Bien entendu, la composition de la variable interne (séparateurs, préfixe, suffixe, etc.) peut être adaptée aux besoins de l'application et du développeur.