Se eu correr
export TEST=foo
echo $TEST
Ele produz foo.
Se eu correr
TEST=foo echo $TEST
Isso não. Como posso obter essa funcionalidade sem usar um script de exportação ou?
Se eu correr
export TEST=foo
echo $TEST
Ele produz foo.
Se eu correr
TEST=foo echo $TEST
Isso não. Como posso obter essa funcionalidade sem usar um script de exportação ou?
Respostas:
Isso ocorre porque o shell expande a variável na linha de comando antes de realmente executar o comando e nesse momento a variável não existe. Se você usar
TEST=foo; echo $TEST
vai funcionar.
export
fará com que a variável apareça no ambiente de comandos executados subseqüentemente (veja como isso funciona no bash help export
). Se você só precisa que a variável apareça no ambiente de um comando, use o que você tentou, ou seja:
TEST=foo your-application
$TEST
antes de a linha de comando ser executada. Uma vez que echo
está em execução (observe também que echo
normalmente será traduzido para o comando interno do shell e não para /bin/echo
), ele vê a variável definida em seu ambiente. No entanto, echo $TEST
não informa echo
a saída do conteúdo da variável TEST
de seu ambiente. Ele diz ao shell para executar echo
com argumento sendo o que está atualmente na variável chamada TEST
- e essas são duas coisas muito diferentes.
var=value sh -c 'echo "$var"'
?
"… $var …"
) , mas não dentro de aspas simples (por exemplo, '… $var …'
). Como echo "$var"
está entre aspas simples, toda a cadeia de caracteres é passada para o sh -c
shell new ( ) sem ser interpretada pelo shell interativo externo. ... (continua)
sh -c
shell filho ( ).
Eu suspeito que você deseja que variáveis de shell tenham um escopo limitado, em vez de variáveis de ambiente. Variáveis de ambiente são uma lista de cadeias de caracteres passadas para comandos quando são executadas .
No
var=value echo whatever
Você está passando a var=value
string para o ambiente que o eco recebe. No entanto, echo
não faz nada com sua lista de ambientes e, de qualquer maneira, na maioria dos shells, echo
é incorporado e, portanto, não é executado .
Se você tivesse escrito
var=value sh -c 'echo "$var"'
Isso teria sido outra questão. Aqui, estamos passando var=value
para o sh
comando e sh
, por acaso, usamos seu ambiente. Os shells convertem cada uma das variáveis que recebem de seu ambiente em uma variável de shell, para que a var
variável de ambiente sh
recebida seja convertida em uma $var
variável e, quando a expandir nessa echo
linha de comando, ela se tornará echo value
. Como o ambiente é herdado por padrão, echo
também receberá var=value
em seu ambiente (ou seria se fosse executado), mas, novamente, echo
não se importa com o ambiente.
Agora, se eu suspeito, o que você deseja é limitar o escopo das variáveis do shell, existem várias abordagens possíveis.
Portably (Bourne e POSIX):
(var=value; echo "1: $var"); echo "2: $var"
O (...) acima inicia um sub-shell (um novo processo de shell na maioria dos shells), portanto, qualquer variável declarada lá afetará apenas esse sub-shell, portanto, espero que o código acima produza "1: value" e "2:" ou "2: o que-var-foi-definido-antes".
Com a maioria dos shells Bourne, você pode usar funções e o built-in "local":
f() {
local var
var=value
echo "1: $var"
}
f
echo "2: $var"
Com o zsh, você pode usar funções embutidas:
(){ local var=value; echo "1: $var"; }; echo "2: $var"
ou:
function { local var=value; echo "1: $var"; }; echo "2: $var"
Com bash e zsh (mas não ash, pdksh ou AT&T ksh), esse truque também funciona:
var=value eval 'echo "1: $var"'; echo "2: $var"
Uma variante que funciona em mais algumas conchas ( dash
, mksh
, yash
), mas não zsh
(a menos que em sh
/ ksh
emulação):
var=value command eval 'echo "1: $var"'; echo "2: $var"
(usar command
na frente de um built-in especial (aqui eval
) em shells POSIX remove sua especialidade (aqui as atribuições de variáveis delas permanecem em vigor após o retorno))
Você está fazendo isso corretamente, mas a sintaxe do bash é fácil de interpretar mal: você pode pensar que isso echo $TEST
faz echo
com que a busca seja TEST
env var e, em seguida, imprima-a, não é. Tão dado
export TEST=123
então
TEST=456 echo $TEST
envolve a seguinte sequência:
O shell analisa toda a linha de comandos e executa todas as substituições de variáveis, para que a linha de comandos se torne
TEST=456 echo 123
Ele cria os vars temporários definidos antes do comando, para salvar o valor atual de TEST
e substituí-lo por 456; a linha de comando é agora
echo 123
Ele executa o comando restante, que nesse caso imprime 123 no stdout (portanto, o comando shell que permanece permanece nem usa o valor temp de TEST
)
Restaura o valor de TEST
Use printenv, pois não envolve substituição de variável:
>> export TEST=123
>> printenv TEST
123
>> TEST=456 printenv TEST
456
>> printenv TEST && TEST=456 printenv TEST && TEST=789 printenv TEST && printenv TEST
123
456
789
123
>>
printenv
útil para teste / prova de conceito (se comporta como um script, em oposição a echo
)
Você pode fazer isso funcionar usando:
TEST=foo && echo $TEST
TEST=foo
está sendo executado como uma instrução separada - não é apenas configurada no contexto de echo
.