Normalmente, é possível definir uma variável de ambiente para um comando prefixando-a da seguinte forma:
hello=hi bash -c 'echo $hello'
Também sei que podemos usar uma variável para substituir qualquer parte de uma chamada de comando, como a seguir:
$ cmd=bash
$ $cmd -c "echo hi" # equivalent to bash -c "echo hi"
Fiquei muito surpreso ao descobrir que você não pode usar uma variável para prefixar um comando para definir uma variável de ambiente. Caso de teste:
$ prefix=hello=hi
$ echo $prefix # prints hello=hi
$ $prefix bash -c 'echo $hello'
hello=hi: command not found
Por que não consigo definir a variável de ambiente usando uma variável? A parte do prefixo é uma parte especial? Consegui fazê-lo funcionar usando eval na frente, mas ainda não entendo o porquê. Estou usando o bash 4.4.
bash
environment-variables
variable
wbkang
fonte
fonte
env
vez deeval
, qual IIRC é mais seguro, mas mais lento.Respostas:
Eu suspeito que esta é a parte da sequência que está pegando você:
Isso é do manual de referência do Bash na seção Expansão de comando simples.
No
cmd=bash
exemplo, nenhuma variável de ambiente é definida e o bash processa a linha de comandos através da expansão de parâmetros, saindobash -c "echo hi"
.No
prefix=hello=hi
exemplo, novamente não há atribuições de variáveis na primeira passagem; portanto, o processamento continua com a expansão de parâmetros, resultando na primeira palavra dehello=hi
.Depois que as atribuições de variáveis são processadas, elas não são processadas novamente durante a execução do comando.
Veja o processamento e seus resultados em
set -x
:Para uma variação mais segura de "expansão variável" -com- "variáveis de ambiente" que
eval
, considere a sugestão de wjandrea deenv
:Não é estritamente uma atribuição de variável da linha de comando, já que estamos usando a
env
função principal do utilitário de atribuir variáveis de ambiente a um comando, mas cumpre o mesmo objetivo. A$prefix
variável é expandida durante o processamento da linha de comandos, fornecendo o nome = valor paraenv
quem o transmitebash
.fonte
$foo=bar bash -c ...
não funcionará, porque$foo=bar
não é uma atribuição de variável (seja qual for o valor$foo
), porque$foo=bar
não se encaixa noname=value
padrão para atribuição de variável.Porque
$prefix
não é uma tarefa. @ Jeff tem uma explicação mais longa .Você poderia fazer algo semelhante com uma função:
... e você pode até empilhá-las, se quiser:
fonte