1

For the commands:

z=bye
z=hello echo $z
echo $z

I'm expecting to see:

hello
bye

Instead, I'm seeing:

bye
bye

According to the man page (emphasis mine):

3.7.1 Simple Command Expansion

When a simple command is executed, the shell performs the following expansions, assignments, and redirections, from left to right, in the following order.

  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 redirections are expanded (see Shell Expansions). If any words remain after expansion, the first word is taken to be the name of the command and the remaining words are the arguments.
  3. Redirections are performed as described above (see Redirections).
  4. The text after the ‘=’ in each variable assignment undergoes tilde expansion, parameter expansion, command substitution, arithmetic expansion, and quote removal before being assigned to the variable.

If no command name results, the variable assignments affect the current shell environment. In the case of such a command (one that consists only of assignment statements and redirections), assignment statements are performed before redirections. Otherwise, the variables are added to the environment of the executed command and do not affect the current shell environment. If any of the assignments attempts to assign a value to a readonly variable, an error occurs, and the command exits with a non-zero status.

So what am I doing wrong?

Adrian
  • 10,246
  • 4
  • 44
  • 110

2 Answers2

2

So let's get the man page. According to the man page https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Shell-Operation :

the shell does the following:

[...]

  1. Performs the various shell expansions (see Shell Expansions), breaking the expanded tokens into lists of filenames (see Filename Expansion) and commands and arguments.

[...]

  1. Executes the command (see Executing Commands).

First z=hello echo $z is expanded to z=hello echo bye. Then z=hello is assigned and exported, and then echo bye is executed. So the output is bye, the variable z is expanded before it is assigned for the current command.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
1

Ok, so the reason seems to be that the line gets expanded in the context of the line. Not the context of the execution. To see this work, I would have to have a separate function/script to see the change.

fn() { echo $z; }
z=bye
z=hello fn
echo $z

Gives me the output that I was expecting.

Adrian
  • 10,246
  • 4
  • 44
  • 110
  • Some alternative ways to achieve the same: `z=hello bash -c 'echo $z'`, `z=hello printenv z` – P.P Nov 26 '22 at 20:55