${!FOO}
performs a double substitution in bash
, meaning it takes the (string) value of FOO and uses it as a variable name.
zsh
doesn’t support this feature.
Is there a way to make this work the same in bash
and zsh
?
Background:
I’ve got a list of environment variables, like
PATH MAIL EDITOR
and want to first print the variable names and afterwards their values.
This works in bash
but not zsh
:
for VAR in LIST
do
echo $VAR
echo ${!VAR}
done
It should be somehow possible “the old way” with eval
, but I can’t get it to work:
for VAR in LIST
do
echo $VAR
echo `eval \$$VAR`
done
I’m never going to understand why I can’t simply do arbitrary deep substitutions like ${${VAR}}
or even ${${${VAR}}}
if need be, so an explanation for that would be nice, too.
Best Answer
Both bash and zsh have a way to perform indirect expansion, but they use different syntax.
It's easy enough to perform indirect expansion using
eval
; this works in all POSIX and most Bourne shells. Take care to quote properly in case the value contains characters that have a special meaning in the shell.${${VAR}}
doesn't work because it's not a feature that any shell implements. The thing inside the braces must conform to syntax rules which do not include${VAR}
. (In zsh, this is supported syntax, but does something different: nested substitutions perform successive transformations on the same value;${${VAR}}
is equivalent to$VAR
since this performs the identity transformation twice on the value.)