Je peux le faire, mais cela nécessite de faire une chaîne de la variable puis de la déréférencer. Existe-t-il un moyen de le raccourcir en une déclaration plus simple?
#!/bin/bash
FRUITS="BANANA APPLE ORANGE"
BANANA_COLOUR="Yellow"
APPLE_COLOUR="Green or Red"
ORANGE_COLOUR="Blue"
for fruit in $( echo $FRUITS ); do
fruit_colour="${fruit}_COLOUR"
echo $fruit is ${!fruit_colour}
done
J'ai essayé beaucoup de choses comme ${!"${fruit}_COLOUR"}
ou \$${fruit}_COLOUR
et de nombreuses autres variantes, mais la seule façon qui a fonctionné est d'utiliser une chaîne.
!
syntaxe est un indicateur sur la substitution de variable qui dit essentiellement «remplacer deux fois». Cela ne change pas l'exigence que ce qui est à l'intérieur du${…}
doit être un nom de variable. Donc non, vous ne pouvez pas éviter d'utiliser une variable qui contient le nom, sauf si vous utilisez une méthode différente (eval
).Réponses:
Tout d'abord, vous n'avez pas besoin d'utiliser
$(echo $FRUITS)
dans lafor
déclaration. Utiliser juste$FRUITS
suffit. Ensuite, vous pouvez supprimer l'une des lignes à l'intérieur de la boucle, en utilisanteval
.Le
eval
dit simplement à bash de faire une deuxième évaluation de la déclaration suivante (c'est-à-dire une de plus que son évaluation normale). Le\$
survit à la première évaluation en tant que$
, et la prochaine évaluation traite ensuite cela$
comme le début d'un nom de variable, qui se résout en "Jaune", etc.De cette façon, vous n'avez pas besoin d'avoir une étape distincte qui crée une chaîne intermédiaire (ce qui est, je crois, l'objectif principal de votre question).
Pour une méthode alternative, comme mentionné par Patrick dans un commentaire (ci-dessus), vous pouvez utiliser à la place un tableau associatif , dans lequel l'index d'un élément n'a pas besoin d'être un entier. Vous pouvez utiliser une chaîne, comme le nom d'un type de fruit. Voici un exemple, en utilisant le tableau associatif de bash:
la source
Vous pouvez utiliser le bash-builtin
eval
pour ce faire:Notez le signe dollar contre-oblique. Fondamentalement, la ligne «eval» fait
bash
remplacer$fruit
et${fruit_color}
, puis utiliseeval
pour effectuer un deuxième tour de sous-station avant d'appelerecho
.la source
Vous n'avez pas besoin d'une instruction eval.
eval
est un indice dans la plupart des langues que vous faites quelque chose de mal.la source
eval
car au moins les gens savent qu'il est dangereux,${!var}
est à peu près aussi dangereuxbash
(également une vulnérabilité d'injection de commande si elle$chosen_prefix
est sous le contrôle d'un attaquant) et moins de gens en sont conscients. Essayezvar_name='a[$(uname>&2)0]' bash -c 'v=${!var_name}'
. La meilleure approche ici est le tableau associatif.