O problema, revisitado
Francamente, o manual é confuso neste ponto. O manual do GNU Bash diz:
O ambiente para qualquer comando ou função simples [observe que isso exclui builtins] pode ser aumentado temporariamente adicionando um prefixo a ele com atribuições de parâmetro, conforme descrito em Parâmetros do Shell. Essas instruções de atribuição afetam apenas o ambiente visto por aquele comando.
Se você realmente analisar a frase, o que ela está dizendo é que o ambiente para o comando / função foi modificado, mas não o ambiente para o processo pai. Então, isso vai funcionar:
$ TESTVAR=bbb env | fgrep TESTVAR
TESTVAR=bbb
porque o ambiente para o comando env foi modificado antes de ser executado. No entanto, isso não funcionará:
$ set -x; TESTVAR=bbb echo aaa $TESTVAR ccc
+ TESTVAR=bbb
+ echo aaa ccc
aaa ccc
por causa de quando a expansão do parâmetro é executada pelo shell.
Passos do intérprete
Outra parte do problema é que o Bash define essas etapas para seu interpretador:
- Lê sua entrada de um arquivo (consulte Shell Scripts), de uma string fornecida como um argumento para a opção de invocação -c (consulte Chamando Bash) ou do terminal do usuário.
- Divide a entrada em palavras e operadores, obedecendo às regras de citação descritas em Citação. Esses tokens são separados por metacaracteres. A expansão de alias é executada por esta etapa (consulte Aliases).
- Analisa os tokens em comandos simples e compostos (consulte Comandos do Shell).
- Executa as várias expansões de shell (consulte Expansões de shell), dividindo os tokens expandidos em listas de nomes de arquivos (consulte Expansão de nome de arquivo) e comandos e argumentos.
- Executa todos os redirecionamentos necessários (consulte Redirecionamentos) e remove os operadores de redirecionamento e seus operandos da lista de argumentos.
- Executa o comando (consulte Execução de comandos).
- Opcionalmente, aguarda a conclusão do comando e coleta seu status de saída (consulte Status de saída).
O que está acontecendo aqui é que os built-ins não têm seu próprio ambiente de execução, portanto, eles nunca veem o ambiente modificado. Além disso, comandos simples (por exemplo, / bin / echo) não ter uma ennvironment modificada (que é por isso que o exemplo env trabalhou), mas a expansão shell está ocorrendo no atual ambiente na etapa # 4.
Em outras palavras, você não está passando 'aaa $ TESTVAR ccc' para / bin / echo; você está passando a string interpolada (conforme expandida no ambiente atual) para / bin / echo. Nesse caso, como o ambiente atual não tem TESTVAR , você simplesmente passa 'aaa ccc' para o comando.
Resumo
A documentação poderia ser muito mais clara. Ainda bem que existe Stack Overflow!
Veja também
http://www.gnu.org/software/bash/manual/bashref.html#Command-Execution-Environment