alzee
alzee

Reputation: 481

Variable assignment in command substitution

Let's say we have a command output a variable assignment string, say 'var=foo', if I put this command in Command Substitution which looks like $(echo var=foo), it causes 'command not found' error.

[223212 dot@anne ~]$ var=foo
[223226 dot@anne ~]$
[223230 dot@anne ~]$ $(var=foo)
[223235 dot@anne ~]$
[223236 dot@anne ~]$ $(echo var=foo)
bash: var=foo: command not found
[223240 dot@anne ~]$
[224909 dot@anne ~]$ $(echo ls)
a    b    c   d    
[225036 dot@anne ~]$
[225110 dot@anne ~]$ $(echo $(var=foo))
[225116 dot@anne ~]$

Since we can directly put variable assignment in Command Substitution like this $(var=foo) (though it's meaningless I think), and $(echo ls) works as expected as well, why output a assignment in Command Substitution causing error?

This is man bash about Command Substitution:

Command substitution allows the output of a command to replace the command name.

Bash performs the expansion by executing command in a subshell environment and replacing the command substitution with the standard output of the command, with any trailing newlines deleted.

As I understand it, $(echo var=foo) should be replace by var=foo just like $(var=foo).

Am I getting it wrong?

Upvotes: 4

Views: 336

Answers (1)

that other guy
that other guy

Reputation: 123470

Here's man bash:

SIMPLE COMMAND EXPANSION
   When a simple command is executed, the shell performs the fol‐
   lowing expansions, assignments, and redirections, from left to
   right.

   1.     The  words  that  the  parser  has  marked  as variable
          assignments (those  preceding  the  command  name)  and
          redirections are saved for later processing.

   2.     The words that are not variable assignments or redirec‐
          tions are expanded.  If any words remain  after  expan‐
          sion,  the  first  word  is taken to be the name of the
          command and the remaining words are the arguments.
   [...]

In your case, the simple command has a single word $(echo var=foo).

Since there are no words marked as variable assignments (because this word is instead a command substitution), step 1 doesn't apply.

We then move on to step 2, where the word $(echo var=foo) is expanded into var=foo. We don't go back to the first step, we just do what step 2 says: "take the first word as the name of the command".

This is why var=foo is executed as a command instead of being interpreted as an assignment.

Upvotes: 6

Related Questions