Eu suspeito que esta é a parte da sequência que está pegando você:
As palavras que não são atribuições ou redirecionamentos de variáveis são expandidas (consulte Expansões do Shell). Se alguma palavra permanecer após a expansão, a primeira palavra será o nome do comando e as palavras restantes serão os argumentos
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, saindo bash -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 de hello=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
:
$ prefix=hello=hi
+ prefix=hello=hi
$ $prefix bash -c 'echo $hello'
+ hello=hi bash -c 'echo $hello'
-bash: hello=hi: command not found
$ hello=42 bash -c 'echo $hello'
+ hello=42
+ bash -c 'echo $hello'
42
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
:
prefix=hello=hi
env "$prefix" bash -c 'echo "$hello"'
hi
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 para env
quem o transmite bash
.
env
vez deeval
, qual IIRC é mais seguro, mas mais lento.