Возвращение к проблеме
Откровенно говоря, руководство по этому поводу сбивает с толку. В руководстве GNU Bash говорится:
Среда для любой простой команды или функции [обратите внимание, что это исключает встроенные функции] может быть временно расширена путем добавления к ней префиксов с назначением параметров, как описано в разделе «Параметры оболочки». Эти операторы присваивания влияют только на среду, видимую этой командой.
Если вы действительно разбираете предложение, то в нем говорится, что среда для команды / функции изменена, но не среда для родительского процесса. Итак, это будет работать:
$ TESTVAR=bbb env | fgrep TESTVAR
TESTVAR=bbb
потому что среда для команды env была изменена перед ее выполнением. Однако это не сработает:
$ set -x; TESTVAR=bbb echo aaa $TESTVAR ccc
+ TESTVAR=bbb
+ echo aaa ccc
aaa ccc
из-за того, что расширение параметра выполняется оболочкой.
Шаги переводчика
Другая часть проблемы заключается в том, что Bash определяет следующие шаги для своего интерпретатора:
- Считывает ввод из файла (см. Сценарии оболочки), из строки, предоставленной в качестве аргумента для параметра вызова -c (см. Вызов Bash), или из пользовательского терминала.
- Разбивает ввод на слова и операторы, подчиняясь правилам цитирования, описанным в разделе Цитирование. Эти токены разделены метасимволами. На этом шаге выполняется расширение псевдонима (см. Псевдонимы).
- Разбирает токены на простые и составные команды (см. Команды оболочки).
- Выполняет различные расширения оболочки (см. Расширения оболочки), разбивая расширенные токены на списки имен файлов (см. Расширение имени файла), а также команд и аргументов.
- Выполняет все необходимые перенаправления (см. Перенаправления) и удаляет операторы перенаправления и их операнды из списка аргументов.
- Выполняет команду (см. Выполнение команд).
- При желании ожидает завершения команды и собирает ее статус выхода (см. Статус выхода).
Здесь происходит то, что встроенные команды не получают собственной среды выполнения, поэтому они никогда не видят измененную среду. Кроме того, простые команды (например, / bin / echo) действительно получают измененное окружение (поэтому пример env работал), но расширение оболочки происходит в текущем среде на шаге №4.
Другими словами, вы не передаете aaa $ TESTVAR ccc в / bin / echo; вы передаете интерполированную строку (развернутую в текущей среде) в / bin / echo. В этом случае, поскольку в текущей среде нет TESTVAR , вы просто передаете команде 'aaa ccc'.
Резюме
Документация могла бы быть намного яснее. Хорошо, что есть Stack Overflow!
Смотрите также
http://www.gnu.org/software/bash/manual/bashref.html#Command-Execution-Environment