1

Yes, yes, I know you're probably like "Hey, there are hundreds of other people asking this same question", but that's not true; I'm not trying to do something like this:

foo="example1"
bar="example2"
foobar="$foo$bar"

I'm trying to do this:

foo="example1"
$foo="examle2"

But whenever I attempt this, I get an error message that says:

bash: example1=example2: command not found

Any suggestions? Is this even possible?

2
  • Yea, there have been a couple of questions of just this within a day or two. I tried to look but didn't find an answer that would deal with all the usual use-cases. So, @Anon, do you have a particular use case in mind? What you're doing might be better done with arrays or associative arrays.
    – ilkkachu
    Aug 22, 2018 at 19:47
  • @ilkkachu to answer your question, I was using an array that cycled through numbers and then I made a variable for each one that was named whatever variable was selected. The contents of the variable were some text files. So, basically, I was trying to EFFICIENTLY make a textfile updater.
    – Anonymous
    Aug 22, 2018 at 21:41

3 Answers 3

6

Here are some examples:

declare [-g] "${foo}=example2"
declare -n foo='example1'
foo='example2'
eval "${foo}=example2"
mapfile -t "${foo}" <<< 'example2'
printf -v "${foo}" '%s' 'example2'
IFS='' read -r "${foo}" <<< 'example2'
typeset [-g] "${foo}=example2"

As other users said, be careful with eval and with indirect assignments in general.

5
  • Oh duh! I completely forgot declare and eval! Thanks so much! After testing both, eval worked "letter-for-letter", and declare worked once I removed the [ ]s from the first declare code.
    – Anonymous
    Aug 22, 2018 at 21:35
  • @AnonymousUser216 Those brackets mean that the -g option is, well, optional, so it may or may not be present in the actual command (read the synopsis of some man pages to see more examples of this syntax). If you use declare var inside a function, then var will be local; but if you use declare -g var, then var will be global. Although, according to Stéphane Chazelas, the actual explanation is a bit more complicated.
    – nxnev
    Aug 22, 2018 at 22:17
  • Trying again, I ran into another problem; I can't assign variable values using your method that have variables in them. Like eval "${foo}='some text'$bar" outputs Command not found. Help?
    – Anonymous
    Aug 22, 2018 at 23:32
  • @Anon What's the content of ${bar}? Remember that eval is used in this case to trigger 2 "levels" of execution instead of only one: the first one by the shell (which expands ${foo}) and the second one by eval itself (which runs example1=example2 as shell code in the current context). So, if ${bar} holds some value like word1 word2, what eval sees is example1='some text'word1 word2, thus it interprets word1 as part of the assignment, word2 as a command and it tries to export the example1 variable to the word2 command's environment (which doesn't exist, does it?).
    – nxnev
    Aug 23, 2018 at 0:16
  • ${bar} is just one word, but don’t worry, I figured out my problem; ${foo}’s value was a number. -silent facepalm- I had forgotten you couldn’t use plain numbers as variables. I added ‘s’ to the front and it worked like a charm. Thank you for your input, though!
    – Anonymous
    Aug 23, 2018 at 11:13
0

It is possible using eval.

eval $foo="examle2"

Be aware that you should be very sure that the value of $foo can be trusted.

A better alternative is to used indexed arrays, where you don't risk executing arbitrary commands.

0
0
suffix=bzz
declare -g prefix_$suffix=mystr

...and then...

varname=prefix_$suffix
echo ${!varname}

Shamelessly stolen from here.

Edit: As stated by Stephane this is generally a bad idea and should be avoided. Indexed arrays are a better alternative.

6
  • 4
    Like for eval, you should be very sure that the value of $suffix can be trusted. Also note that declare has the side effect of restricting the scope of variables when used in a function. Also note that unquoted parameter expansions are subject to split+glob in bash, you should almost never do that. Aug 22, 2018 at 19:43
  • Note the warning was more in response to the warning about eval in other answers. array[$var]=bar or any variable used in an arithmetic expression is also a command injection vulnerability (and all of declare/read/printf... can interpret arithmetic expressions) Aug 22, 2018 at 21:13
  • @StéphaneChazelas, yeah, I meant to check that there wasn't anything else to watch out for with declare than the arithmetic expansion. Thanks for the link!
    – ilkkachu
    Aug 22, 2018 at 21:25
  • Note that in bash (contrary to zsh/mksh/yash), typeset/declare -g doesn't really do what you want here. See for instance bash -c 'f() { local a=1; g; }; g() { declare -g a=2; echo "$a"; }; f' and bash vs zsh: scoping and `typeset -g` Aug 22, 2018 at 21:42

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .