Quando usar ponto e vírgula entre variáveis ​​de ambiente e um comando

Quando usar ponto e vírgula entre variáveis ​​de ambiente e um comando

Alguém pode explicar por que o ponto e vírgula é necessário para que LANGseja visto como atualizado pelo bash?

Não funciona:

> LANG=Ja_JP bash -c "echo $LANG"
en_US

Funciona:

> LANG=Ja_JP ; bash -c "echo $LANG"
Ja_JP

Estou trabalhando com o bash 4.1.10 no linux e a mesma versão no cygwin

Responder1

Parâmetro e outros tipos de expansões são executados quando o comando é lido,antesele é executado.

A primeira versão, LANG=Ja_JP bash -c "echo $LANG", é um comando único. Depois de analisado como tal, $LANGé expandido para en_USantes de qualquer coisa ser executada. Assim que bashterminar de processar a entrada, ele bifurca um processo, adiciona LANG=Ja_JPao ambiente conforme esperado e, em seguida, executa bash -c echo en_US.

Você pode evitar a expansão com aspas simples, ou seja, LANG=Ja_JP bash -c 'echo $LANG'outputs Ja_JP.

Observe que quando você tem uma atribuição de variável como parte de um comando, a atribuição afeta apenas o ambiente desse comando e não o do seu shell.

A segunda versão LANG=Ja_JP; bash -c "echo $LANG"consiste, na verdade, em dois comandos separados executados em sequência. A primeira é uma simples atribuição de variável sem comando, afetando seu shell atual.

Assim, seus dois trechos são fundamentalmente diferentes, apesar da distinção superficial de um único arquivo ;.

Completamente fora do assunto, mas recomendo anexar um .UTF-8arquivo LANG. Não há nenhuma boa razão hoje em dia para não usar o Unicode no século XXI.

Responder2

VAR=value; somecommandé equivalente a

VAR=value
somecommand

Estes são comandos não relacionados executados um após o outro. O primeiro comando atribui um valor à variável shell VAR. A menos que VARjá seja uma variável de ambiente, ela não é exportada para o ambiente, permanece interna ao shell. Uma declaração export VARseria exportada VARpara o meio ambiente.

VAR=value somecommandé uma sintaxe diferente. A atribuição VAR=valueé para o ambiente, mas esta atribuição só é feita no ambiente de execução do somecommand, não para a execução posterior do shell.

A título de exemplo:

# 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

Responder3

Este é o resumo do que colhi da pesquisa:

Existem dois tipos: variáveis ​​de ambiente e variáveis ​​de shell.

Uma variável de ambiente está disponível em um programa e seus programas/processos/subshells filhos. Uma variável shell está disponível apenas no shell atual.

https://askubuntu.com/a/26322/326584

Primeiro como echo $VARfunciona

Sempre que o terminal/shell/bash vê o símbolo $, ele faz algo chamado "expansão de parâmetros". O que significa que variáveis ​​são substituídas por valores.

https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html

Então, se VARtivesse o valor 'hello', então echo $VARse tornaria echo 'hello'.

o que significa que isso funciona ...

TEST=123 
echo $TEST
// 123

mas o seguinte não funciona porque a variável foi substituída ANTES de o comando poder definir a variável.

TEST2=999 echo $TEST2
// nothing...

mas se você adicionar o ponto e vírgula ..

TEST2=999; echo $TEST2

é o mesmo que..

TEST2=999
echo $TEST2

.. que funciona da mesma forma que antes.

E como as variáveis ​​do shell não são passadas para subprocessos/filho, quando você chama um comando ele cria um novo processo, então...

TEST3=111 
node -e 'console.log(process.env.TEST3)' 

ou

TEST3=111 
printenv TEST3

ambos não imprimem nada. Variáveis ​​de shell não são herdadas por processos chld. Use export para tornar a variável shell, uma variável de ambiente.

export TEST3=111 
printenv TEST3
//111

Há uma exceção...

VAR=123 printenv VAR
VAR=123 VAR2=456 printenv VAR2 //even multiple vars

Basicamente, se for escrito assim e logo após chamar o comando, ele definirá apenas temporariamente o ambiente var para esse comando. Ele nem mesmo define o shell var. Pense nisso como uma sintaxe completamente nova.

VAR=123 printenv VAR // 123
echo $VAR // nothing
VAR=123
echo $VAR // 123

informação relacionada