Suivi de la partie historique de cette question .
En bash
je peux utiliser ${!FOO}
pour la double substitution, en zsh
${(P)FOO}
. Dans les deux, la vieille école (hack-y) eval \$$FOO
fonctionne.
Donc, la chose la plus intelligente et la plus logique pour moi serait la ${${FOO}}, ${${${FOO}}}…
substitution double / triple / n. Pourquoi cela ne fonctionne-t-il pas comme prévu?
Deuxièmement: que fait \
la eval
déclaration? Je pense que c'est une évasion, rendant quelque chose comme eval \$$$FOO
impossible. Comment faire une substitution triple / n avec celle qui fonctionne dans chaque shell?
la source
l3=l2; eval eval eval echo \\\$\\$\$$l3
→53294
donc pas exactement modulaire.eval $(eval echo \$$l2)
? Je déteste bash, ça n'a absolument aucun sens.la source
Supposons que la valeur de
FOO
est un nom de variable valide (par exempleBAR
),eval \$$FOO
divise la valeur deBAR
en mots séparés, traite chaque mot comme un motif générique et exécute le premier mot du résultat comme une commande, en passant les autres mots comme arguments. La barre oblique inverse devant le dollar le fait être traité littéralement, donc l'argument passé à la commandeeval
intégrée est la chaîne de quatre caractères$BAR
.${${FOO}}
est une erreur de syntaxe. Il ne fait pas de «double substitution» car il n'y a aucune telle fonctionnalité dans aucun des shells communs (pas avec cette syntaxe de toute façon). Dans zsh,${${FOO}}
est valide et est une double substitution, mais il se comporte différemment de ce que vous aimeriez: il effectue deux transformations successives sur la valeur deFOO
, qui sont toutes les deux la transformation d'identité, donc c'est juste une façon d'écrire de fantaisie${FOO}
.Si vous souhaitez traiter la valeur d'une variable comme une variable, veillez à bien citer les choses. C'est beaucoup plus facile si vous définissez le résultat sur une variable:
la source
{ba,z}sh
SolutionVoici une fonction qui fonctionne dans les deux
{ba,z}sh
. Je pense qu'il est également conforme à POSIX.Sans devenir fou avec la citation, vous pouvez l'utiliser pour de nombreux niveaux d'indirection comme ceci:
Ou si vous avez plus (!?!) De niveaux d'indirection, vous pouvez utiliser une boucle.
Il prévient lorsqu'il est donné:
la source
Tout comme
${$foo}
ne fonctionne pas à la place de${(P)foo}
danszsh
, ni ne fait${${$foo}}
. Il vous suffit de spécifier chaque niveau d'indirection:Bien sûr,
${!${!foo}}
ne fonctionne pasbash
, carbash
ne permet pas les substitutions imbriquées.la source
zsh
est installé beaucoup plus souvent que vous ne le pensez. Il peut ne pas être lié àsh
commebash
souvent (mais pas toujours), mais il peut toujours être disponible pour les scripts shell. Pensez-y comme vous le faites Perl ou Python.Pourquoi auriez-vous besoin de faire ça?
Vous pouvez toujours le faire en plusieurs étapes comme:
Ou utilisez une fonction comme:
Ensuite:
FWIW, dans
zsh
:la source
Solution POSIX
Sans devenir fou avec la citation, vous pouvez utiliser cette fonction pour de nombreux niveaux d'indirection comme ceci:
Ou si vous avez plus (!?!) De niveaux d'indirection, vous pouvez utiliser une boucle.
Il prévient lorsqu'il est donné:
la source