variable="Something"
var2="variable";
echo "\$$(echo $var2)"
In the last line, you expect "\$$(echo $var2)"
→ $variable
→ Something
.
This would require the shell to perform two parameter expansions. It does not, but rather simply prints the result of the command substitution $(echo $var2)
prepended by a $
.
In principle, eval helps you to get what you want. After the shell performs the first step, "\$$(echo $var2)"
→ $variable
, eval performs the second step, $variable
→ Something
.
$ eval echo "\$$(echo $var2)"
Something
Although in our particular case the above command is OK, that still lacks a correct quoting, and printf
is to be favored over echo
,
$ eval 'printf "%s\n" "${'"$var2"'}"'
Something
However, eval raises security concerns with untrusted data. Suppose
var2="variable;rm importantFile"
. In that case, eval passes
echo $variable;rm importantFile
to the shell, which happily removes importantFile
, if it exists.
In some shells (e.g.: Bash, ksh, Zsh) you can also do it using indirection. The syntax of indirect expansion in Bash is:
$ echo "${!var2}"
Something
var2="variable;rm importantFile"
is not a problem anymore,
but var2='a[$(rm importantFile)]'
still is.
Read more about indirection in the Bash manual.
If the first character of parameter is an exclamation
point (!), and parameter is not a nameref, it introduces a level of indirection.
Bash uses the value formed by expanding the rest of parameter as the new parameter;
this is then expanded and that value is used in the rest of the expansion,
rather than the expansion of the original parameter
echo "$(echo $var2)"
? Incidentally you should also quote the$var2
. So it becomesecho "$(echo "$var2")"
. However in this example it won't matter (the bug is latent). – ctrl-alt-delor Jul 22 '20 at 19:14"\$$(echo $var2)"
would evaluate to '$variable'. So why doesn't UNIX understand that I'm trying to do echo $variable (indirectly), and print out whatever is stored in variable. I'm referring to the second part – Swaroop Joshi Jul 22 '20 at 19:44$variable
be replaced with a value just doesn't happen, because it's not part of the execution model to re-evaluate expansion results as code (unless the user runseval
or such). So we can't really give you an answer that says "it doesn't parse as code because thing-X happens", when the reality is more like "it doesn't parse as code because in order for that to happen, there would need to be step-Y, and that just isn't part of the model". – Charles Duffy Jul 23 '20 at 14:40