${!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 souhaitez d'abord imprimer les noms des variables et ensuite leurs valeurs.
Cela fonctionne 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 ne peux 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.
la source
bash
, il a en effet la même fonction (et bien plus), n'utilise qu'un modèle différent, à savoir${(p)FOO}
.(e)
drapeau d'expansion des paramètres de zsh a été ajouté dans zsh-2.6-beta17 (mai 1996), le(P)
drapeau dans 3.1.5-pws-7 (1999). bash's${!var}
en 2.0 (décembre 1996).Réponses:
Bash et zsh ont tous deux 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. Prenez soin de citer correctement au cas où la valeur contient des caractères qui ont une signification spéciale dans le shell.${${VAR}}
ne fonctionne pas car ce n'est pas une fonctionnalité implémentée par un shell. La chose à l'intérieur des accolades doit être conforme aux règles de syntaxe qui ne comprennent 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
car cela effectue la transformation d'identité deux fois sur la valeur.)la source
Le commentaire, sous la question d'origine, par Profpatsch donne l'exemple
${(p)FOO}
de sortie du contenu d'une référence de variable indirecte. Le drapeau est incorrect ou une faute de frappe, il doit s'agir d'un P majuscule et non d'un p minuscule. Utilisation:${(P)FOO}
.Les éléments suivants devraient produire la sortie souhaitée:
Depuis la page de manuel zshexpn ; section - Indicateurs d'extension des paramètres :
À un moment donné, j'ai lu pourquoi
${${${VAR}}}
ne produit pas la sortie que vous attendiez, mais à ce moment-là, je ne le trouve pas. Vous pouvez faire quelque chose comme ceci:la source
Vous n'utilisez pas eval correctement. Dans votre exemple, la valeur de $ VAR précédée d'un "$" (c'est-à-dire "$ VALUE") serait exécutée comme une commande. Ce n'est pas ce que tu veux. Vous souhaitez évaluer l'expansion d'une variable dont le nom est tiré d'une autre variable.
la source
{ba,z}sh
SolutionVoici une fonction qui fonctionne à la fois {ba, z} sh. Je pense qu'il est également conforme à POSIX.
Il prévient lorsqu'il est donné:
la source
function
ni ni[[...]]
dans POSIXsh
.[ "$#" -eq 0 ]
(ou probablement[ "$#" -ne 1 ]
car vous n'attendez qu'un seul argument).shell-check
pourrait aider aussi.${1-}
donnéea='"" -o -n 1'
[ -z $a ]
==0
. Mais ne sera-t-il pas$#
toujours un seul jeton?