${!FOO}
effectue une double substitution dans bash
, ce qui signifie qu'il prend la valeur (chaîne) de FOO et l'utilise comme nom de variable.zsh
ne prend pas en charge cette fonctionnalité.
Existe-t-il un moyen de faire en sorte que cela fonctionne de la même manière dans bash
et zsh
?
Contexte :
J'ai une liste de variables d'environnement, comme
PATH MAIL EDITOR
et que vous voulez d'abord imprimer les noms des variables et ensuite leurs valeurs.
Cela fonctionne dans bash
mais pas zsh
:
for VAR in LIST
do
echo $VAR
echo ${!VAR}
done
Cela devrait être en quelque sorte possible "à l'ancienne" avec eval
, mais je n'arrive pas à le faire fonctionner :
for VAR in LIST
do
echo $VAR
echo `eval $$VAR`
done
Je ne comprendrai jamais pourquoi je ne peux pas simplement faire des substitutions profondes arbitraires comme ${${VAR}}
ou même ${${${VAR}}}
si besoin est, donc une explication serait bien aussi.
Réponse acceptée :
bash et zsh ont un moyen d'effectuer une expansion indirecte, mais ils utilisent une syntaxe différente.
Il est assez facile d'effectuer une expansion indirecte en utilisant eval
; cela fonctionne dans tous les shells POSIX et la plupart des shells Bourne. Veillez à bien citer les guillemets au cas où la valeur contiendrait des caractères ayant une signification particulière dans le shell.
eval "value="${$VAR}""
echo "$VAR"
echo "$value"
${${VAR}}
ne fonctionne pas car ce n'est pas une fonctionnalité qu'un shell implémente. La chose à l'intérieur des accolades doit être conforme aux règles de syntaxe qui n'incluent pas ${VAR}
. (Dans zsh, cette syntaxe est prise en charge, mais fait quelque chose de différent :les substitutions imbriquées effectuent des transformations successives sur la même valeur ; ${${VAR}}
est équivalent à $VAR
puisque cela effectue la transformation d'identité deux fois sur la valeur.)