211 votes

Comment obtenir la valeur d'une variable si le nom de la variable est stocké sous forme de chaîne de caractères ?

Comment récupérer la valeur d'une variable bash si le nom de la variable est une chaîne de caractères ?

var1="this is the real value"
a="var1"
Do something to get value of var1 just using variable a.

Contexte :

J'ai quelques AMI ( Image de la machine Amazon ) et je veux lancer quelques instances de chaque AMI. Dès que le démarrage est terminé, je veux configurer chaque instance en fonction de son type d'AMI. Je ne veux pas intégrer beaucoup de scripts ou de clés secrètes dans une AMI, j'ai donc préparé un scripts de démarrage généralisé et je l'ai placé dans le fichier S3 avec un lien accessible au public. Dans rc.local, je place un petit morceau de code qui récupère le script de démarrage et l'exécute. C'est tout ce que j'ai dans les AMI. Ensuite, chaque AMI accède à une configuration commune script qui s'applique à toutes les AMI et à des script spéciaux pour chacune d'entre elles. Ces script sont privés et nécessitent une URL signée pour y accéder.

Ainsi, lorsque je lance une instance d'une AMI (my_private_ami_1), je transmets une URL signée pour un autre fichier présenté sur S3 qui contient l'URL signée pour tous les scripts privés en termes de paires clé/valeur.

config_url="http://s3.amazo.../config?signature"
my_private_ami_1="http://s3.amazo.../ami_1?signature"
...

Lorsque le script de démarrage s'exécute, il télécharge le fichier ci-dessus et source c'est cela. Ensuite, il vérifie son type d'AMI et choisit la bonne configuration script pour lui-même.

ami\_type=GET AMI TYPE #ex: sets ami\_type to my\_private\_ami\_1
setup\_url=GET THE SETUP FILE URL BASED ON AMI\_TYPE # this is where this problem arises

J'ai donc maintenant un code générique qui peut déclencher des instances indépendamment de leur type d'AMI et les instances peuvent s'occuper d'elles-mêmes.

388voto

Phil Ross Points 10227

Vous pouvez utiliser ${!a} :

var1="this is the real value"
a="var1"
echo "${!a}" # outputs 'this is the real value'

Il s'agit d'un exemple d'action indirecte expansion des paramètres :

La forme de base de l'expansion des paramètres est la suivante ${parameter} . T parameter est substitué.

Si le premier caractère de parameter est un point d'exclamation ( !), il introduit un niveau d'indirection de la variable. Bash utilise la valeur de la formée à partir du reste de la variable parameter a Cette variable est ensuite développée et le reste de la substitution, plutôt que la valeur de parameter même.

38voto

X=foo
Y=X
eval "Z=\$$Y"

ensembles Z a foo .

21voto

Smac89 Points 1926

Pour mes collègues utilisateurs de zsh, la façon d'accomplir la même chose que la réponse acceptée est d'utiliser :

echo ${(P)a} # outputs 'this is the real value'

Il s'appelle à juste titre Remplacement du nom du paramètre

Cela force la valeur du nom du paramètre à être interprétée comme un dont la valeur sera utilisée le cas échéant. Notez que les drapeaux définis avec l'une des commandes de la famille des caractères d'imprimerie (dans la section (en particulier les transformations) ne sont pas appliqués à la valeur du nom utilisée de cette manière.

S'il est utilisé avec un paramètre imbriqué ou une substitution de commande, le résultat de la commande sera pris comme nom de paramètre de la même manière. Par exemple, si vous avez "foo=bar" et "bar=baz", les chaînes ${(P)foo}, ${(P)${foo}} et ${(P)$(echo bar)} seront développées en "baz".

De même, si la référence est elle-même imbriquée, l'expression avec l'attribut est traitée comme si elle était directement remplacée par le nom du paramètre. C'est une erreur si cette substitution imbriquée produit un tableau avec plus de plus d'un mot. Par exemple, si 'name=assoc' où le paramètre assoc est un tableau associatif, alors "${${(P)name}[elt]}" fait référence à l'élément de l'élément associatif souscrit "elt".

12voto

bhups Points 6257

J'ai modifié mes mots-clés de recherche et je l'ai obtenu :).

eval a=\$$a

Merci pour votre temps.

11voto

Mr Z Points 31

En bash 4.3+, vous pouvez utiliser declare -n :

#!/usr/bin/env bash

var="this is the real value"
var_name="var"

declare -n var_ref=$var_name
echo "${var_ref}"

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X