I am trying to unset some variables and export others using command substitution. This works:
$(echo " export TEST_A=1 export TEST_B=2 ")
And this too:
$(echo " unset TEST_A unset TEST_B ")
However, this fails with Bash 4.3.30(1)-release on both OSX and Debian Jessie:
$(echo " unset TEST_A export TEST_B=1 ") # bash: unset: `TEST_B=1': not a valid identifier
Is this an expected behavior, and how can one unset and export multiple variables using command substitution?
To provide some context: here is the related issue in boot2docker.
$(...), just one expansion is parsed as a simple command.
$(...) expansion undergoes the split+glob operator. The output of
echo is trimmed of its trailing newline characters and split into several words on IFS characters (newline, space and tab by default):
And each word undergoes globbing. Here they expand to themselves since they don't contain wildcard characters. So after globbing, we still have the same list of four strings.
The command to run is derived from the first one. Here
export and all those strings are passed as arguments to that command. So, here, it's as if you had written:
export TEST_A=1 export TEST_B=2
So you're exporting the
TEST_A variable with value 1, the
export variable without changing its value and the
TEST_B variable with value 2.
In the last one, you're running:
unset TEST_A export TEST_B=1
If you want the output of
echo to be treated as shell code to interpret, that's where you want to use
eval and not use the split+glob operator (quote your command substitution):
eval "$(echo "
That one is also a simple command. Two strings:
<newline><spaces>unset TEST_A<newline><spaces>export TEST_B=1.
eval evaluates the content of its arguments as shell code. So it runs those two shell command lines:
unset TEST_A and
export TEST_B=1 (again, two simple commands).