
Alguém pode explicar por que o ponto e vírgula é necessário para que LANG
seja 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_US
antes de qualquer coisa ser executada. Assim que bash
terminar de processar a entrada, ele bifurca um processo, adiciona LANG=Ja_JP
ao 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-8
arquivo 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 VAR
já seja uma variável de ambiente, ela não é exportada para o ambiente, permanece interna ao shell. Uma declaração export VAR
seria exportada VAR
para 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 $VAR
funciona
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 VAR
tivesse o valor 'hello', então echo $VAR
se 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