Double and triple substitution in bash and zsh
The \
must be used to prevent the expansion of $$
(current process id). For triple substitution, you need double eval, so also more escapes to avoid the unwanted expansions in each eval:
#! /bin/bash
l0=value
l1=l0
l2=l1
l3=l2
l4=l3
echo $l0
eval echo \$$l1
eval eval echo \\$\$$l2
eval eval eval echo \\\\$\\$\$$l3
eval eval eval eval echo \\\\\\\\$\\\\$\\$\$$l4
#!/bin/bash
hello=world
echo=hello
echo $echo ${!echo}
Supposing the value of FOO
is a valid variable name (say BAR
), eval \$$FOO
splits the value of BAR
into separate words, treats each word as a wildcard pattern, and executes the first word of the result as a command, passing the other words as arguments. The backslash in front of the dollar makes it be treated literally, so the argument passed to the eval
builtin is the four-character string $BAR
.
${${FOO}}
is a syntax error. It doesn't do a “double substitution” because there's no such feature in any of the common shells (not with this syntax anyway). In zsh, ${${FOO}}
is valid and is a double substitution, but it behaves differently from what you'd like: it performs two successive transformations on the value of FOO
, both of which are the identity transformation, so it's just a fancy way of writing ${FOO}
.
If you want to treat the value of a variable as a variable, be careful of quoting things properly. It's a lot easier if you set the result to a variable:
eval "value=\${$FOO}"