Seems that the recommended way of doing indirect variable setting in bash is to use eval
:
var=x; val=foo eval $var=$val echo $x # --> foo
The problem is the usual one with eval
:
var=x; val=1$'\n'pwd eval $var=$val # bad output here
(and since it is recommended in many places, I wonder just how many scripts are vulnerable because of this...)
In any case, the obvious solution of using (escaped) quotes doesn't really work:
var=x; val=1\"$'\n'pwd\" eval $var=\"$val\" # fail with the above
The thing is that bash has indirect variable reference baked in (with ${!foo}
), but I don't see any such way to do indirect assignment -- is there any sane way to do this?
For the record, I did find a solution, but this is not something that I'd consider "sane"...:
eval "$var='"${val//\'/\'\"\'\"\'}"'"
Bash uses the value of the variable formed from the rest of parameter as the name of the variable; this variable is then expanded and that value is used in the rest of the substitution, rather than the value of parameter itself. This is known as indirect expansion.
A variable in bash can contain a number, a character, a string of characters. You have no need to declare a variable, just assigning a value to its reference will create it.
Example 28-1. Indirect referencing in Bash is a multi-step process. First, take the name of a variable: varname. Then, reference it: $varname. Then, reference the reference: $$varname.
A parameter is an entity that stores values. It can be a name , a number, or one of the special characters listed below. A variable is a parameter denoted by a name . A variable has a value and zero or more attributes .
A slightly better way, avoiding the possible security implications of using eval
, is
declare "$var=$val"
Note that declare
is a synonym for typeset
in bash
. The typeset
command is more widely supported (ksh
and zsh
also use it):
typeset "$var=$val"
In modern versions of bash
, one should use a nameref.
declare -n var=x x=$val
It's safer than eval
, but still not perfect.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With