Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Indirect variable assignment in bash

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//\'/\'\"\'\"\'}"'" 
like image 587
Eli Barzilay Avatar asked Mar 30 '12 07:03

Eli Barzilay


People also ask

What is indirect expansion in bash?

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.

Can you assign variables in bash?

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.

How to reference variable bash?

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.

What is a parameter in bash?

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 .


1 Answers

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.

like image 158
chepner Avatar answered Sep 20 '22 15:09

chepner