Если я бегу
export TEST=foo
echo $TEST
Это выводит foo.
Если я бегу
TEST=foo echo $TEST
Это не. Как я могу получить эту функциональность без использования экспорта или сценария?
shell
environment-variables
echo
ashleysmithgpu
источник
источник
Ответы:
Это связано с тем, что оболочка раскрывает переменную в командной строке до того, как она фактически запускает команду, и в то время переменная не существует. Если вы используете
это будет работать.
export
заставит переменную появиться в среде впоследствии выполненных команд (смhelp export
., как это работает в bash ). Если вам нужно, чтобы переменная появлялась только в среде одной команды, используйте то, что вы пробовали, т.е.источник
$TEST
перед выполнением командной строки. После того,echo
как выполняется (также обратите внимание, чтоecho
это обычно переводится во встроенную команду оболочки, а не в/bin/echo
), она видит набор переменных в своей среде. Однакоecho $TEST
не говоритecho
выводить содержимое переменнойTEST
из ее окружения. Он говорит оболочке запускатьсяecho
с аргументом, который в настоящее время находится в переменной, называемойTEST
- и это две совершенно разные вещи.var=value sh -c 'echo "$var"'
?"… $var …"
), но не внутри одинарных кавычек (например,'… $var …'
). Посколькуecho "$var"
внутри одиночных кавычек, вся строка передается вsh -c
оболочку new ( ) без интерпретации внешней интерактивной оболочкой. … (Продолжение)sh -c
дочерней оболочкой new ( ).Я подозреваю, что вы хотите, чтобы переменные оболочки имели ограниченную область видимости, а не переменные среды. Переменные среды представляют собой список строк, передаваемых командам при их выполнении .
В
Вы передаете
var=value
строку в среду, которую получает эхо. Темecho
не менее, ничего не делает со своим списком окружения и, в любом случае, в большинстве оболочекecho
он встроен и поэтому не выполняется .Если бы вы написали
Это было бы другое дело. Здесь мы проходим
var=value
кsh
команде, иsh
случается использовать его окружение. Оболочки преобразуют каждую из переменных, которые они получают из своей среды, в переменную оболочки, поэтому полученныеvar
переменные средыsh
будут преобразованы в$var
переменную, и когда она развернет ее в этойecho
командной строке, это станетecho value
. Поскольку среда по умолчанию наследуется,echo
она также получаетvar=value
в своей среде (или получит, если бы она была выполнена), но, опять же,echo
не заботится об окружающей среде.Теперь, если, как я подозреваю, вам нужно ограничить область действия переменных оболочки, есть несколько возможных подходов.
Портативно (Борн и POSIX):
(...) выше запускает под-оболочку (новый процесс оболочки в большинстве оболочек), поэтому любая объявленная там переменная будет влиять только на эту под-оболочку, поэтому я ожидаю, что приведенный выше код выведет «1: значение» и «2:» или «2: все, что было установлено ранее».
С большинством Bourne-подобных оболочек вы можете использовать функции и встроенную «локальную» функцию:
С zsh вы можете использовать встроенные функции:
или же:
С bash и zsh (но не с ash, pdksh или AT & T ksh) этот прием также работает:
Вариант , который работает в течение еще нескольких оболочек (
dash
,mksh
,yash
) , но неzsh
(если вsh
/ksh
эмуляции):(использование
command
перед встроенным (здесьeval
) в оболочках POSIX исключает их особенность (здесь присваивание переменных из них остается в силе после их возвращения))источник
Вы делаете это правильно, но синтаксис bash легко неверно истолковать: вы можете подумать, что
echo $TEST
приводитecho
к извлечениюTEST
env var, а затем распечатывает его, а это не так. Так данотогда
включает в себя следующую последовательность:
Оболочка анализирует всю командную строку и выполняет все подстановки переменных, поэтому командная строка становится
Он создает временные переменные, установленные перед командой, поэтому сохраняет текущее значение
TEST
и перезаписывает его с помощью 456; командная строка сейчасОн выполняет оставшуюся команду, которая в этом случае печатает 123 в стандартный вывод (так что оставшаяся команда оболочки даже не использовала временное значение
TEST
)Восстанавливает ценность
TEST
Вместо этого используйте printenv, поскольку он не требует подстановки переменных:
источник
printenv
полезным для тестирования / доказательства концепции (ведет себя как сценарий, а не какecho
)Вы можете получить это с помощью:
источник
TEST=foo
выполняется как отдельный оператор - он не просто устанавливается в контекстеecho
.