Где недоступно «var var = value»?

31

Я понял - вероятно, на Usenet в середине 1990-х (!) - что конструкция

export var=value

является Bashism, и что переносимое выражение

var=value
export var

Я защищал это годами, но недавно кто-то бросил мне вызов, и я действительно не могу найти никаких документов, подтверждающих то, что раньше было моим твердым убеждением.

"export: command not found"Похоже, поиск в Google не приводит ни к каким случаям, когда кто-то действительно имел эту проблему, поэтому, даже если она подлинная, я думаю, что это не очень распространено.

(Удары , которые я получаю , кажется, новички , которые копировать / вставить знаки препинания, и в конечном итоге с 'export: command not foundили несколько таких, или пытаются использовать exportс sudo, и новичком csh. Пользователей пытаются использовать синтаксис Bourne оболочки)

Я, конечно, могу сказать, что он работает на OS X и на разных дистрибутивах Linux, включая те, где shесть dash.

sh$ export var=value
sh$ echo "$var"
value
sh$ sh -c 'echo "$var"'  # see that it really is exported
value

Можно ли сказать, что в современном мире export var=valueбезопасно использовать?

Я хотел бы понять, каковы последствия. Если он не портативен для v7 "Bourne classic", это вряд ли что-то большее, чем мелочи. Если существуют производственные системы, в которых оболочка действительно не справляется с этим синтаксисом, это было бы полезно знать.

tripleee
источник
2
спасибо, я наконец понял, почему я так часто вижу то, что мне показалось бесполезным: var = value; export var
Thorsten Staerk
2
Есть еще несколько коробок Solaris, которые, как известно, скромны в своих стандартных инструментах; на другом конце спектра, не имеет busyboxсвоей собственной минимальной оболочки? (Я не в состоянии попробовать ни того, ни другого прямо сейчас.)
Ульрих Шварц
Благодаря Ульриху, Solaris вполне может быть виновником, почему этот длинный синтаксис все еще существует.
Торстен Стаерк

Ответы:

20
export foo=bar

не был поддержан оболочкой Bourne (старая оболочка 70-х годов, из которой происходят современные shреализации, такие как ash / bash / ksh / yash / zsh). Это было введено ksh.

В оболочке Bourne вы бы сделали:

foo=bar export foo

или:

foo=bar; export foo

или с set -k:

export foo foo=bar

Теперь о поведении:

export foo=bar

варьируется от оболочки к оболочке.

Проблема в том, что присваивания и простые командные аргументы анализируются и интерпретируются по-разному.

foo=barВыше интерпретируются некоторыми оболочки в качестве аргумента команды и других как назначение (иногда).

Например,

a='b c'
export d=$a

интерпретируется как:

'export' 'd=b' 'c'

с некоторыми оболочками ( ashболее старые версии zsh(в эмуляции sh), yash) и:

'export' 'd=b c'

в других ( bash, ksh).

В то время как

export \d=$a

или

var=d
export $var=$a

будет интерпретироваться одинаково во всех оболочках (как 'export' 'd=b' 'c'), потому что обратный слеш или знак доллара останавливает те оболочки, которые его поддерживают, чтобы рассматривать эти аргументы как присваивания.

Если exportсам по себе указан или является результатом некоторого расширения (даже частично), в зависимости от оболочки, он также перестанет получать специальную обработку.

См. « Нужны ли кавычки для присваивания локальной переменной? » Для более подробной информации об этом.

Хотя синтаксис Борна:

d=$a; export d

интерпретируется одинаково всеми оболочками без двусмысленности ( d=$a export dтакже работает в оболочке Bourne и POSIX-совместимых оболочках, но не в последних версиях, zshесли только не в shэмуляции).

Это может стать намного хуже, чем это. Посмотрите, например, это недавнее обсуждение того,bash когда задействованы массивы.

(ИМО, было ошибкой вводить эту функцию ).

Стефан Шазелас
источник
Я был удивлен, что точка с запятой не требуется foo=bar export foo, как я всегда видел там. Я знаю, что экспорт является встроенным, но почему он foo=bar; foo=baz export foo; echo $fooведет себя иначе, чем foo=bar; foo=baz /bin/cat /dev/null; echo $foo?
jrw32982 поддерживает Монику
3
@ jrw32982, потому что это встроенный. Вы все еще получаете что в современном POSIX оболочках , но только для специальных встроенных команд , которые exportесть.
Стефан Шазелас
Хотя это и обсуждает declare, но exportя рекомендую всем, кто заботится о безопасности, прочитать обсуждение по ссылке, которую StéphaneChazelas предоставил bash.bugs .
John1024
Отличный ответ! Но потребовалось много времени, чтобы все d=$a export dинтерпретировалось одинаково всеми оболочками без двусмысленности ;-)
Конни
@conny, d=$a export dбольше не работает zsh, поэтому я обновил ответ. Смотрите редактировать.
Стефан Шазелас
28

Это не bashism, а POSIX-совместимый синтаксис. На самом деле он начинался как kshism довольно давно, а позже был принят практически всеми оболочками, основанными на синтаксисе Борна. Единственное общеизвестное исключение - /bin/shSolaris 10 и старше, который придерживается устаревшего синтаксиса оболочки Bourne. Надеемся, что Solaris 11 использует POSIX-совместимую оболочку как /bin/sh.

Кстати, это exportбыла уже встроенная команда в устаревшей оболочке Bourne, поэтому поиск в Google export: command not foundвводил в заблуждение.

Вот унаследованное поведение оболочки Bourne в exportсочетании с влиянием:

$ export var=22
var=22: is not an identifier

Для ностальгии исходный код этой оригинальной оболочки Bourne доступен и может быть скомпилирован для большинства дистрибутивов Unix и Linux.

jlliagre
источник
Большое спасибо за историческое понимание и правильное сообщение об ошибке для Google! Очевидно, в ретроспективе, румянец ...
tripleee
4
Это не исходный код оригинальной оболочки Bourne, это модифицированный OpenSolaris sh. Это оболочка Борна, но после десятилетий эволюции. Оригинальную оболочку Bourne, поставляемую с Unix V7, можно найти в Обществе наследия Unix
Стефан Шазелас
1
@ StéphaneChazelas Строго говоря, ты, как обычно, прав. Однако обратите внимание, что я написал не «оригинальную оболочку Bourne», а «эту оригинальную оболочку Bourne», поскольку имел в виду оболочку, используемую Solaris 10, и ее исходный код, который можно скомпилировать на современных платформах. Также обратите внимание, что оболочка Bourne имела несколько функций, добавленных между 1977 и 1989 годами, но затем по существу перестала развиваться (вне портирования / адаптации к более новым платформам и исправлениям ошибок) за последние 25 лет или около того.
Jlliagre