Isso se resume a uma questão de como a avaliação funciona. Ambos os exemplos funcionam da mesma maneira, o problema ocorre devido à forma como o shell (bash, aqui) expande variáveis.
Quando você escreve este comando:
HOME="foo" echo $HOME
O $HOME
é expandido antes da execução do comando . Portanto, ele é expandido para o valor original e não o novo valor definido para o comando. A HOME
variável foi realmente alterada no ambiente em que o echo
comando está sendo executado; no entanto, você está imprimindo a $HOME
partir do pai.
Para ilustrar, considere o seguinte:
$ HOME="foo" bash -c 'echo $HOME'
foo
$ echo $HOME
/home/terdon
Como você pode ver acima, o primeiro comando imprime o valor alterado temporariamente HOME
e o segundo imprime o original, demonstrando que a variável foi alterada apenas temporariamente. Como o bash -c ...
comando está entre aspas simples ( ' '
) em vez de aspas duplas ( " "
), a variável não é expandida e é passada como está para o novo processo do bash. Esse novo processo o expande e imprime o novo valor para o qual foi definido. Você pode ver isso acontecer se você usar set -x
:
$ set -x
$ HOME="hello" echo "$HOME"
+ HOME=hello
+ echo hello
hello
Como você pode ver acima, a variável $HOME
nunca é passada para echo
. Ele vê apenas seu valor expandido. Compare com:
$ HOME="hello" bash -c 'echo $HOME'
+ HOME=hello
+ bash -c 'echo $HOME'
hello
Aqui, devido às aspas simples, a variável e não seu valor são passadas para o novo processo.
local
.eval
solução deve ser evitada?Existem dois escopos: variáveis de ambiente e variáveis locais. As variáveis de ambiente são válidas para todos os processos (consulte
setenv
,getenv
), enquanto as variáveis locais estão ativas apenas nesta sessão do shell. (Não é uma distinção óbvia ...)Implícito
env
(como no seu exemplo) modifica o ambiente, enquantoecho ...
usa os locais - portantoenv
, não tem efeito.Para modificar as variáveis locais, use, digamos,
Aqui os parênteses definem o escopo dessa atribuição.
fonte