Your first guess was right, but you used a bad example.
When the shell reads the command
foo=bar echo $foo
the first thing it does (or, at least, one of the first things)
is to look for variable references (like
$foo) and evaluate them.
Then it processes what’s left of the line.
(This may be a bit of an oversimplification;
bash(1) or the Bash Reference Manual for details.)
So you have the command
foo=bar; but it’s too late; there’s nothing left to look at the value of
You can demonstrate this with the following sequence:
$ foo=bar echo "$foo"
is the way to go. A couple of examples that work are:
foo=bar sh -c 'echo "$foo"'
(You may want to pipe that through
I just now noticed the sentence that you quoted,
“When those assignment statements precede a command that is built into the shell, for instance, …”,
suggesting that built-in commands (such as
echo) represent a special case.
It is intuitive (to me, at least) that this “command scope” you’re looking for
would have to work by setting an environment variable in a child process,
and it’s not clear how it would work for a built-in command, which doesn’t run in a child process.
Not many built-in commands access the environment directly,
and their interaction with shell variables is sometimes arcane.
But I came up with a couple more examples that might be more what you’re looking for:
foo=bar eval 'echo $foo'
will display “bar”, because the evaluation of
$foo is deferred.
It is handled by the
eval (built-in) command, rather than the shell’s initial parsing pass.
Or, create a text file called (for instance)
echo $foo (or
echo "$foo") command into it, and say
foo=bar . showme.sh
This is probably what your book is talking about when it says,
“… the shell has to keep track of the correct order in which to resolve variable references ….”
Somehow the shell runs the commands in
foo equal to
and then reverts to the previous value of
foo (if any)
when it gets back to its primary input (the terminal).