Чтобы понять, почему strong> это ведет себя не только в bash, но и в любой совместимой оболочке:
2.10.2, Правила грамматики оболочки
Из правила 7(b), охватывающего случаи, когда присваивание предшествует простой команде:
Если все символы, предшествующие '=', образуют допустимое имя (см. том «Базовые определения» стандарта IEEE Std 1003.1-2001, раздел 3.230, «Имя»), должен быть возвращен маркер ASSIGNMENT_WORD. (Символы в кавычках не могут участвовать в формировании допустимого имени.)
[...]
Присвоение NAME должно происходить, как указано в Простых командах.
Таким образом, синтаксический анализ этого назначения требуется для POSIX-совместимой оболочки.
2.9.1, Простые команды
Перенаправления должны выполняться, как описано в Перенаправлении.
Каждое назначение переменной должно быть расширено для расширения с помощью тильды, расширения параметра, подстановки команд, арифметического расширения и удаления кавычек перед присвоением значения.
[...]
Если имя команды не получено, присвоение переменных должно повлиять на текущую среду выполнения. В противном случае назначения переменных должны быть экспортированы для среды выполнения команды и не должны влиять на текущую среду выполнения (за исключением специальных встроенных функций). Если какое-либо из назначений переменных попытается присвоить значение к переменной только для чтения, должна произойти ошибка назначения переменной. См. Последствия ошибок оболочки, чтобы узнать о последствиях этих ошибок.
Таким образом: назначение, данное в части префикса простой команде, должно быть экспортировано и не должно влиять на текущую среду оболочки, если только вызываемая команда не является специальной встроенной. Кроме того, эти шаги должны следовать за перенаправлениями, которые по своей природе должны происходить на поздних этапах процесса вызова команды.
2.12, Среда выполнения оболочки
Утилиты, отличные от специальных встроенных (см. Специальные встроенные утилиты), должны вызываться в отдельной среде, состоящей из следующего. Начальное значение этих объектов должно быть таким же, как и для родительской оболочки, за исключением указанного ниже.
[...]
Переменные с атрибутом экспорта, вместе с теми, которые явно экспортируются на время выполнения команды, должны быть переданы в переменные среды утилиты.
Таким образом: эти переменные расширяются подоболочкой после fork и перед выполнением вызываемой команды и должны - по спецификации - влиять только на дочернюю среду.
Теперь о другом поведении:
SOMEVAR=BBB sh -c 'echo "$SOMEVAR"'
... выигрывает от того, что экземпляр sh
создает переменные оболочки из своих переменных среды (как требуется в разделе 2.5.3 спецификации POSIX) при запуске.
Кстати, стоит отметить, что синтаксис, о котором вы спрашиваете, предназначен для присваивания внутри простой команды, а не присваивания внутри вложенной оболочки. Вы можете управлять назначением в подоболочке, участвующей в конвейере, следующим образом:
{ SOMEVAR=BBB; echo "$SOMEVAR"; } | somecommand ...
... который помещает назначение в подоболочку, выполняющую первый компонент конвейера (если ваша оболочка действительно запускает этот компонент в подоболочке, что является неопределенным поведением в отношении POSIX; из спецификации: как расширение , однако любая или все команды в конвейере могут выполняться в текущей среде).
person
Charles Duffy
schedule
22.06.2015