${!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.)