Разница между экспортируемыми переменными оболочки и теми, которых нет в bash

41

Bash, кажется, различает переменные, которые были экспортированы, и переменные, которые не были экспортированы.

пример:

$ FOO=BAR
$ env | grep FOO
$ set | grep FOO
FOO=BAR

setвидит переменную, но envне видит .

$ export BAR=FOO
$ env | grep FOO
BAR=FOO
$ set | grep FOO
BAR=FOO
FOO=BAR

setвидит обе переменные, но envвидит только экспортированную переменную.

Я знаю, что setэто встроенный Bash, а envне.

Каковы различия между переменными, которые экспортируются, и переменными, которые не экспортируются?

lesmana
источник
17
Замечание по терминологии: «переменная среды» всегда экспортируется. Неэкспортированная переменная - это «переменная оболочки» (или «параметр»).
Жиль "ТАК ... перестать быть злым"

Ответы:

44

Экспортируемые переменные переносятся в среду команд, выполняемых оболочкой, которая их экспортировала, в то время как неэкспортированные переменные являются локальными для текущего вызова оболочки. Со exportстраницы руководства :

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

setвыводит текущую среду, которая включает в себя все локальные неэкспортированные переменные. envиспользуется для запуска программ в новой среде и без аргументов выведет, какой будет эта новая среда. Поскольку envсоздается новая среда, передаются только экспортированные переменные, как в случае любой программы, запускаемой из этой оболочки. Например, порождение второй оболочки внутри первой (я использовал $$для представления подсказок во внутренней оболочке):

$ FOO=BAR
$ bash
$$ echo $FOO             # Note the empty line

$$ exit
$ export FOO
$ bash
$$ echo $FOO
BAR
$$

Обратите внимание, что экспортируется переменная, а не только ее значение. Это означает, что, как только вы export FOO, FOOстановитесь глобальной переменной и отображаются в последующих средах, даже если изменились позже:

$ export FOO
$ FOO=BAR
$ bash
$$ echo $FOO
BAR
$$
Михаил Мрозек
источник
так что если вас беспокоит только текущая оболочка, вам нужно экспортировать? Отдельно, почему бы localeдля текущей оболочки не показывать обновления?
Пейсер