65

I want to declare a variable, the name of which comes from the value of another variable, and I wrote the following piece of code:

a="bbb"
$a="ccc"

but it didn't work. What's the right way to get this job done?

1
  • If you are on Bash 5+ the better solution is nearly always an associative array. The duplicate has several demonstrations of this. Commented Jan 4, 2023 at 7:18

6 Answers 6

70

In highly portable shell code, eval is used for this, but if you do it naively, there are going to be nasty escaping issues. This sort of thing is generally safe:

name_of_variable=abc

eval $name_of_variable="simpleword"   # abc set to simpleword

This breaks:

eval $name_of_variable="word splitting occurs"

The fix:

eval $name_of_variable="\"word splitting occurs\""  # not anymore

The ultimate fix: put the text you want to assign into a variable. Let's call it safevariable. Then you can do this:

eval $name_of_variable=\$safevariable  # note escaped dollar sign

Escaping the dollar sign solves all escape issues. The dollar sign survives verbatim into the eval function, which will effectively perform this:

eval 'abc=$safevariable' # dollar sign now comes to life inside eval!

And of course this assignment is immune to everything. safevariable can contain *, spaces, $, etc. (The caveat being that we're assuming name_of_variable contains nothing but a valid variable name, and one we are free to use: not something special.)

The Korn shell introduces something called namerefs which Bash also implements. With namerefs we can do this directly:

declare -n foo=bar

Now foo is a nameref which holds the name bar. The nameref behaves as a variable. When we assign to foo, we are actually assinging to bar, and $foo produces the value $bar. It's like a symbolic link for variables.

Namerefs provide a much cleaner and safer solution for indirecting on variables than eval at the loss of maximal portability.

Sign up to request clarification or add additional context in comments.

3 Comments

So the $safevariable is the $safe_target_value to assign the variable name saved in $name_of_variable ?
eval $name_of_variable="word\ splitting\ occurs" also works
It works only if the backslashes remain part of the string and aren't eaten during the initial parsing pass. That's not documented/guaranteed/version-independent behavior.
68

You can use declare and !, like this:

John="nice guy"
programmer=John
echo ${!programmer} # echos nice guy

Second example:

programmer=Ines
declare $programmer="nice gal"
echo $Ines # echos nice gal

6 Comments

Hi Flimm. Is it possible with arrays ? Something like echo "${!array[1]}" ?
@leaf: Maybe the -a-option of declare helps? See declare --help, and test for yourself.
It is nice gesture to say such nice things about your colleagues :D:D
Just a note, this will not work inside a function, for that I found KAz' eval solution to work.
Bash docs call the ${!var_name} form "indirect expansion": gnu.org/software/bash/manual/html_node/…
|
21

This might work for you:

foo=bar
declare $foo=baz
echo $bar
baz

or this:

foo=bar
read $foo <<<"baz"
echo $bar
baz

6 Comments

correct, better to use declare over eval (security reasons)
@meso_2600 declare does not behave the same way as assignment, because it will change the scope of the variable to the local one (you won't be able to modify a variable from a parent scope with declare, unless you declare it as a global variable).
your second answer is great. no subshell spawned. cheers.
@niieani: According to declare --help, the -g option to declare always declares a global variable.
@GolarRamblar that's correct. I didn't state otherwise, unless you're referring to something else?
|
9

You could make use of eval for this.
Example:

$ a="bbb"
$ eval $a="ccc"
$ echo $bbb
ccc

Hope this helps!

Comments

8

If you want to get the value of the variable instead of setting it you can do this

var_name1="var_name2"
var_name2=value_you_want
eval temp_var=\$$var_name1
echo "$temp_var"

You can read about it here indirect references.

Comments

-3

You can assign a value to a variable using simple assignment using a value from another variable like so:

#!/usr/bin/bash

#variable one
a="one"

echo "Variable a is $a"
#variable two with a's variable
b="$a"

echo "Variable b is $b"

#change a
a="two"
echo "Variable a is $a"
echo "Variable b is $b"

The output of that is this:

Variable a is one
Variable b is one
Variable a is two
Variable b is one

So just be sure to assign it like this b="$a" and you should be good.

1 Comment

The question is how to indirect upon computed variable names, now how to assign expressions fixed variables.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.