In:
$(echo "
export TEST_A=1
export TEST_B=2
")
being $(...)
, just one expansion is parsed as a simple command.
So that $(...)
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):
export
TEST_A=1
export
TEST_B=2
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 "
unset TEST_A
export TEST_B=1
")"
That one is also a simple command. Two strings: eval
and <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).
unset
command last, it has no effect. Try this:$(printf "export A=1\nexport B=2") && echo "A: $A, B: $B"
, then$(printf "export C=3\nunset A") && echo "A: $A, B: $B, C: $C"
. You'll see thatA
is still set.