Это сводится к вопросу о том, как работает оценка. Оба примера работают одинаково, проблема возникает из-за того, что оболочка (здесь, bash) расширяет переменные.
Когда вы пишете эту команду:
HOME="foo" echo $HOME
$HOME
Расширяется до команды запуска . Следовательно, оно расширяется до исходного значения, а не до нового значения, установленного для команды. HOME
Переменная действительно были изменены в среде , что echo
команда работает в, однако, вы печатаете $HOME
от родителя.
Для иллюстрации рассмотрим это:
$ HOME="foo" bash -c 'echo $HOME'
foo
$ echo $HOME
/home/terdon
Как вы можете видеть выше, первая команда печатает временно измененное значение, HOME
а вторая печатает оригинал, демонстрируя, что переменная была изменена только временно. Поскольку bash -c ...
команда заключена в одинарные кавычки ( ' '
) вместо двойных ( " "
), переменная не раскрывается и передается как есть новому процессу bash. Этот новый процесс затем расширяет его и печатает новое значение, для которого он был установлен. Вы можете увидеть это, если вы используете set -x
:
$ set -x
$ HOME="hello" echo "$HOME"
+ HOME=hello
+ echo hello
hello
Как вы можете видеть выше, переменная $HOME
никогда не передается echo
. Он видит только его расширенное значение. Сравнить с:
$ HOME="hello" bash -c 'echo $HOME'
+ HOME=hello
+ bash -c 'echo $HOME'
hello
Здесь из-за одинарных кавычек переменная, а не ее значение передаются новому процессу.
local
.eval
избегать решения?Есть две области: переменные окружения и локальные переменные. Переменные среды действительны для каждого процесса (см.
setenv
,getenv
), В то время как локальные переменные активны только в этом сеансе оболочки. (Это не очевидное различие ...)Подразумевается
env
(как в вашем примере) изменяет среду, в то время какecho ...
использует локальные - такenv
что не имеет никакого эффекта.Для изменения локальных переменных используйте, скажем,
Здесь круглые скобки определяют объем этого назначения.
источник