It's because of the order in which bash parses the command line. It looks for variable definitions (e.g. a=b
) before performing variable and command substitution (e.g. commands in backticks). Because of this, by the time echo $x
is replaced by a=b
, it's too late for bash to see this as a variable definition and it's parsed as a command instead. The same thing would've happened if you'd just used $x
as the command (instead of echo in backticks). As in @mvds's answer, the eval
command can be used to force the command to be reparsed from the beginning, meaning that it'll be recognized as a variable definition:
$ x="a=b"
$ `echo $x`
-bash: a=b: command not found
$ $(echo $x) # Exact same thing, but with cleaner syntax
-bash: a=b: command not found
$ $x # This also does the same thing, but without some extra steps
-bash: a=b: command not found
$ eval "$x" # This will actually work
$ echo $a
b
$ a= # Start over
$ eval "$(echo "$x")" # Another way of doing the same thing, with extra steps
$ echo $a
b
Note that when using eval
I've put all of the references to $x
in double-quotes -- this is to prevent the later phases of bash parsing (e.g. word splitting) from happening twice, since bash will finish its regular parsing process, then recognize the eval
command, and then redo the entire parsing process again. It's really easy to get unexpected results from using eval
, and this removes at least some of the potential for trouble.