
Может ли кто-нибудь объяснить, почему точка с запятой необходима для того, чтобы LANG
bash считал файл обновленным?
Не работает:
> LANG=Ja_JP bash -c "echo $LANG"
en_US
Работает:
> LANG=Ja_JP ; bash -c "echo $LANG"
Ja_JP
Я работаю как с bash 4.1.10 на Linux, так и с той же версией под Cygwin.
решение1
Параметр и другие типы расширений выполняются при чтении команды,доон выполнен.
Первая версия, LANG=Ja_JP bash -c "echo $LANG"
, представляет собой одну команду. После того, как она проанализирована как таковая, $LANG
она расширяется до , en_US
прежде чем что-либо будет выполнено. После bash
завершения обработки ввода она разветвляет процесс, добавляется LANG=Ja_JP
в среду, как и ожидалось, а затем выполняется bash -c echo en_US
.
Вы можете предотвратить расширение с помощью одинарных кавычек, т. е. LANG=Ja_JP bash -c 'echo $LANG'
outputs Ja_JP
.
Обратите внимание, что если вы назначаете переменную как часть команды, то это назначение влияет только на среду этой команды, а не на среду вашей оболочки.
Вторая версия, LANG=Ja_JP; bash -c "echo $LANG"
на самом деле, представляет собой две отдельные команды, выполняемые последовательно. Первая — это простое назначение переменной без команды, поэтому она влияет на вашу текущую оболочку.
Таким образом, ваши два фрагмента принципиально различны, несмотря на поверхностное различие в виде одного ;
.
Совершенно не по теме, но могу ли я порекомендовать добавлять a .UTF-8
при настройке LANG
. В настоящее время нет никаких веских причин не использовать Unicode в 21 веке.
решение2
VAR=value; somecommand
эквивалентно
VAR=value
somecommand
Это несвязанные команды, выполняемые одна за другой. Первая команда присваивает значение переменной оболочки VAR
. Если VAR
она уже не является переменной среды, она не экспортируется в среду, она остается внутренней для оболочки. Оператор export VAR
экспортирует VAR
в среду.
VAR=value somecommand
— это другой синтаксис. Назначение VAR=value
выполняется для среды, но это назначение выполняется только в среде выполнения somecommand
, а не для последующего выполнения оболочки.
В качестве примера:
# Assume neither VAR1 nor VAR2 is in the environment
VAR1=value
echo $VAR1 # displays "value"
env | grep '^VAR1=' # displays nothing
VAR2=value env | grep '^VAR2=' # displays "VAR2=value"
echo $VAR2 # displays nothing
решение3
Вот краткое изложение того, что я почерпнул в ходе исследования:
Существует два типа: переменные окружения и переменные оболочки.
Переменная окружения доступна в программе и ее дочерних программах/процессах/подоболочках. Переменная оболочки доступна только в текущей оболочке.
https://askubuntu.com/a/26322/326584
Первое, как echo $VAR
работает
Всякий раз, когда терминал/оболочка/bash видит символ $, он делает то, что называется "расширением параметров". Это означает, что переменные заменяются значениями.
https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
Таким образом, если VAR
имелось значение «привет», то echo $VAR
становится echo 'hello'
.
что означает, что это работает...
TEST=123
echo $TEST
// 123
но следующее не работает, потому что переменная была заменена ДО того, как команда смогла установить переменную.
TEST2=999 echo $TEST2
// nothing...
но если добавить точку с запятой..
TEST2=999; echo $TEST2
это то же самое, что и ..
TEST2=999
echo $TEST2
.. который работает так же, как и раньше.
А поскольку переменные оболочки не передаются в подпроцессы/дочерние процессы, при вызове команды создается новый процесс, поэтому...
TEST3=111
node -e 'console.log(process.env.TEST3)'
или
TEST3=111
printenv TEST3
оба ничего не печатают. Переменные оболочки не наследуются дочерними процессами. Используйте экспорт, чтобы сделать переменную оболочки переменной окружения.
export TEST3=111
printenv TEST3
//111
Есть одно исключение...
VAR=123 printenv VAR
VAR=123 VAR2=456 printenv VAR2 //even multiple vars
В принципе, если написать это так и сразу после вызова команды, то это только временно устанавливает переменную окружения для этой команды. Это даже не устанавливает переменную оболочки. Думайте об этом как о совершенно новом синтаксисе.
VAR=123 printenv VAR // 123
echo $VAR // nothing
VAR=123
echo $VAR // 123