Как правило, для команды можно установить переменную среды, добавив к ней префикс следующим образом:
hello=hi bash -c 'echo $hello'
Я также знаю, что мы можем использовать переменную для замены любой части вызова команды, например:
$ cmd=bash
$ $cmd -c "echo hi" # equivalent to bash -c "echo hi"
Я был очень удивлен, узнав, что вы не можете использовать переменную для префикса команды для установки переменной среды. Прецедент:
$ prefix=hello=hi
$ echo $prefix # prints hello=hi
$ $prefix bash -c 'echo $hello'
hello=hi: command not found
Почему я не могу установить переменную среды, используя переменную? Префиксная часть - это особенная часть? Мне удалось заставить его работать, используя eval, но я до сих пор не понимаю, почему. Я использую Bash 4.4.
env
Вместо этого вы можете использоватьeval
, который IIRC является более безопасным, но медленнее.Ответы:
Я подозреваю, что это часть последовательности, которая ловит вас:
Это из справочного руководства по Bash в разделе «Простое расширение команд».
В этом
cmd=bash
примере переменные окружения не установлены, и bash обрабатывает командную строку через расширение параметра, оставляяbash -c "echo hi"
.В этом
prefix=hello=hi
примере снова нет присвоений переменных на первом проходе, поэтому обработка продолжается до раскрытия параметра, в результате чего появляется первое словоhello=hi
.Как только назначения переменных были обработаны, они не обрабатываются повторно во время выполнения команды.
Смотрите обработку и ее результаты в разделе
set -x
:Для более безопасной вариации «переменное расширение», как «переменные окружения»
eval
, рассмотрим предложение wjandreaenv
:Это не строго присваивание переменной командной строки, так как мы используем
env
основную функцию утилиты для присвоения переменных среды команде, но она выполняет ту же цель.$prefix
Переменный расширяются во время обработки командной строки, обеспечивая имя = значениеenv
, который передает его вместе сbash
.источник
$foo=bar bash -c ...
же не будет работать, потому что$foo=bar
не является присвоением переменной (каким бы ни было значение$foo
), потому$foo=bar
что не соответствуетname=value
шаблону для назначения переменной.Потому что
$prefix
это не задание. У @Джеффа есть более длинное объяснение .Вместо этого вы можете сделать то же самое с функцией:
... и вы можете даже сложить их, если хотите:
источник