Ваше первое предположение было верным, но вы использовали плохой пример.
Когда оболочка читает команду
foo=bar echo $foo
первое, что он делает (или, по крайней мере, одно из первых), это ищет ссылки на переменные (например, $foo) и оценивает их.
Затем он обрабатывает то, что осталось от линии.
(Это может быть немного упрощением; подробнее см. bash(1) или Справочное руководство Bash .)
Итак, у вас есть команда
echo (nothing)
работает с foo=bar ; но уже слишком поздно; там ничего не осталось, чтобы посмотреть на значение $foo .
Вы можете продемонстрировать это с помощью следующей последовательности:
$ foo=oldvalue
$ foo=bar echo "$foo"
oldvalue
Но
foo=bar command
это путь. Несколько примеров, которые работают:
foo=bar sh -c 'echo "$foo"'
а также
foo=bar env
(Вы можете хотеть передать это через grep foo .)
Я только что заметил предложение, которое вы цитировали:«Когда эти операторы присваивания предшествуют команде, встроенной в оболочку, например,…», предполагая, что встроенные команды (такие как echo) представляют собой особый случай.
Интуитивно понятно (по крайней мере для меня), что эта «область команд», которую вы ищете, должна работать, устанавливая переменную среды в дочернем процессе, и неясно, как она будет работать для встроенной команды, который не работает в дочернем процессе.
Немногие встроенные команды обращаются к среде напрямую, и их взаимодействие с переменными оболочки иногда является загадочным.
Но я придумал еще пару примеров, которые могут быть больше, чем вы ищете:
foo=bar eval 'echo $foo'
будет отображаться «bar», потому что оценка $foo отложена.
Он обрабатывается командой eval (встроенной), а не начальным этапом синтаксического анализа оболочки.
Или создайте текстовый файл с именем (например) showme.sh .
Вставьте в него команду echo $foo (или echo "$foo") и скажите
foo=bar . showme.sh
Это, вероятно, то, о чем говорит ваша книга, когда говорится: «… оболочка должна отслеживать правильный порядок разрешения ссылок на переменные…».
Каким-то образом оболочка выполняет команды в showme.sh с foo равным bar , и затем возвращается к предыдущему значению foo (если оно есть), когда возвращается к своему первичному входу (терминалу).