Le problème, revu et corrigé
Très franchement, le manuel est confus sur ce point. Le site Manuel de GNU Bash dit :
L'environnement de toute commande ou fonction simple [notez que cela exclut les buildins] peut être augmenté temporairement en le préfixant avec des affectations de paramètres, comme décrit dans Paramètres du shell. Ces instructions d'affectation n'affectent que l'environnement vu par cette commande.
Si vous analysez vraiment la phrase, ce qu'elle dit c'est que la environnement pour la commande/fonction est modifié, mais pas l'environnement pour le processus parent. Donc, cela va fonctionner :
$ TESTVAR=bbb env | fgrep TESTVAR
TESTVAR=bbb
car l'environnement de la commande env a été modifié avant son exécution. Cependant, cela ne fonctionnera pas :
$ set -x; TESTVAR=bbb echo aaa $TESTVAR ccc
+ TESTVAR=bbb
+ echo aaa ccc
aaa ccc
en raison du moment où l'expansion des paramètres est effectuée par le shell.
Étapes de l'interprétation
Une autre partie du problème est que Bash définit ces étapes pour son interprète :
- Lit son entrée depuis un fichier (voir Shell scripts), depuis une chaîne de caractères fournie en tant qu'argument de l'option d'invocation -c (voir Invocation de Bash). Bash), ou depuis le terminal de l'utilisateur.
- Décompose l'entrée en mots et en opérateurs, en respectant les règles de citation. décrites dans Citation. Ces tokens sont séparés par des métacaractères. L'expansion des alias est effectuée par cette étape (voir Alias).
- Analyse les tokens en commandes simples et composées (voir Commandes Shell).
- Effectue les diverses expansions du shell (voir Expansions du shell), en décomposant les tokens expansés en listes de noms de fichiers (cf. Expansion), de commandes et d'arguments.
- Effectue toutes les redirections nécessaires (voir Redirections) et supprime les opérateurs de redirection et leurs opérandes de la liste d'arguments.
- Exécute la commande (voir Exécution des commandes).
- Optionnellement, attend que la commande se termine et collecte sa sortie. de sortie (voir État de sortie).
Ce qui se passe ici est que les buildins n'obtiennent pas leur propre environnement d'exécution, donc ils ne voient jamais l'environnement modifié. En outre, les commandes simples (par exemple, /bin/echo) faire obtient un ennvironnement modifié (c'est pourquoi l'exemple env a fonctionné) mais l'expansion de l'interpréteur de commandes a lieu dans le répertoire actuel à l'étape 4.
En d'autres termes, vous ne passez pas 'aaa $TESTVAR ccc' à /bin/echo ; vous passez la chaîne interpolée (telle qu'elle est développée dans l'environnement actuel) à /bin/echo. Dans ce cas, puisque l'environnement actuel n'a pas de code TESTVAR vous passez simplement 'aaa ccc' à la commande.
Résumé
La documentation pourrait être beaucoup plus claire. Heureusement qu'il y a Stack Overflow !
Voir aussi
http://www.gnu.org/software/bash/manual/bashref.html#Command-Execution-Environment