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

14

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

Não funciona:

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

Trabalho:

> 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

Richard Corden
fonte

Respostas:

23

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

A primeira versão,, LANG=Ja_JP bash -c "echo $LANG"é um único comando. Depois de analisado como tal, $LANGé expandido para en_USantes de qualquer coisa ser executada. Uma vez que bashestá terminado o processamento da entrada, ele bifurca um processo, acrescenta LANG=Ja_JPao ambiente como esperado, e então executa bash -c echo en_US.

Você pode impedir a expansão com aspas simples, ou seja, LANG=Ja_JP bash -c 'echo $LANG'saídas 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"na verdade , são dois comandos separados executados em sequência. A primeira é uma atribuição simples de variável sem um comando, portanto afeta o shell atual.

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

Completamente fora do tópico, mas recomendo anexar a .UTF-8quando definir LANG. Atualmente, não há uma boa razão para não usar o Unicode no século XXI.

jw013
fonte
Ótima resposta - obrigado! Em relação à adição de UTF-8. Estou tentando testar a manipulação de localidade de um aplicativo que precisa funcionar em várias plataformas, algumas das quais bastante antigas. Entre diferenças como essa (que felizmente você explicou) e diferenças no linux e cygwin, estou prestes a me jogar debaixo de um ônibus!
Richard Corden
5

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 do shell VAR. A menos que VARjá seja uma variável de ambiente, não seja exportada para o ambiente, ela permanece interna no shell. Uma declaração export VARseria exportada VARpara o ambiente.

VAR=value somecommandé uma sintaxe diferente. A atribuição VAR=valueé para o ambiente, mas essa atribuição é feita apenas no ambiente de execução de somecommand, não para a execução subsequente 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
Gilles 'SO- parar de ser mau'
fonte
Eu realmente não tinha pensado na diferença entre uma variável de ambiente shell vs. Vou ter que fazer uma pesquisa. Obrigado pela resposta.
Richard Corden