Когда следует использовать точку с запятой между переменными среды и командой

Когда следует использовать точку с запятой между переменными среды и командой

Может ли кто-нибудь объяснить, почему точка с запятой необходима для того, чтобы LANGbash считал файл обновленным?

Не работает:

> 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

Связанный контент