I need to declare variables in a bash shell script for which both names and values are taken from another command's output.
For the sake of this question, I will use a temporary file tmp
:
$ cat tmp
var1="hello world"
var2="1"
... and use it for my mock command below.
In the end, I need to have the variables $var1
and $var2
set with respectively hello world
and 1
, with the variable names var1
and var2
taken directly from the input.
Here is what I got so far:
$ cat tmp|while read line; do declare $line; done
I know I don't need to use cat
but this is to simulate the fact that the input is taken from the output of an other command and not in a file.
This doesn't work. I get:
bash: declare: `world"': not a valid identifier
and
$ echo $var1; echo $var2
$
I don't understand why this doesn't work since I can do this:
declare var1="hello world"
... with expected result. I assumed this would be equivalent, but I'm clearly wrong.
I found this answer as the closest thing to my problem, but not quite since it relies on a file to source. I would like to avoid that. I found other answers that uses eval
but I'd prefer to avoid that as well.
Maybe there are subtleties in the use of quotes I don't understand.
If the only way is to use a temporary file and source it that is what I'll do, but I think there must be another way.
A good suggestion when writing a shell script is that always double quoting the variable. Otherwise, it will be affected by the shell word splitting.
while read line; do
declare "$line"
done < <(echo "var1=hello world")
And why echo "var1=hello world" | while read line; do export "$line"; done
won't work? Because pipe
is a sub-shell
, it creates var1
in the sub-shell, it won't impact the current shell. So it can't be set in the current shell.
As an alternative, use process substitution
, you can obtain the output as a temporary file. So it will create the variable in the current shell.