TL; DR: dans le cas de export FOO=bar, bash invoque sa création d'environnement temporaire, définit FOO=bardans cet environnement, puis donne une commande finale de export FOO. À ce stade, FOOest pris comme dernier argument.
Ah, les abusés $_:
($ _, un trait de soulignement.) Au démarrage du shell, définissez le chemin d'accès absolu utilisé pour appeler le shell ou le script de shell en cours d'exécution tel que transmis dans l'environnement ou la liste d'arguments. Par la suite, se développe jusqu'au dernier argument de la commande précédente, après expansion. Définissez également le chemin d'accès complet utilisé pour appeler chaque commande exécutée et placée dans l'environnement exporté vers cette commande. Lors de la vérification du courrier, ce paramètre contient le nom du fichier courrier.
Regardons quelques variantes:
$ man; echo $_
What manual page do you want?
man
$ man foo; echo $_
No manual entry for foo
foo
$ echo; echo $_
echo
$ echo bar foo; echo $_
bar foo
foo
$ foo=x eval 'echo $foo'; echo $_
x
echo $foo
$ bar() { man $1; }; echo $_
foo
$ for (( i=0; $i<0; i=i+1 )); do echo $i; done; echo $_
foo
$ bar; echo $_
What manual page do you want?
man
$ bar foo; echo $_
No manual entry for foo
foo
$ MANPATH=/tmp; echo $_
$ export MANPATH=/tmp; echo $_
MANPATH
Nous voyons donc trois modèles ici:
- Les commandes invoquées depuis le système de fichiers, les fonctions et les commandes intégrées se comportent comme prévu:
$_est défini sur le nom de la commande lui-même si aucun argument, sinon le dernier des arguments présentés.
- Après définitions de fonctions, boucles et autres constructions logiques:
$_n'est pas modifié.
- Tout le reste:
$_est réglé sur quelque chose qui n'est pas tout à fait attendu; bizarre.
J'ai instrumenté le code pour donner un aperçu de l'étrangeté.
$ ./bash --noprofile --norc -c 'man foo'
lastword=[man]
lastarg=[foo]
$ ./bash --noprofile --norc -c 'export FOO=bar'
lastword=[export]
lastarg=[FOO=bar]
bind_variable, name=[FOO], value=[bar]
before bind_lastarg, lastarg=[FOO]
bind_lastarg, arg=[FOO]
bind_variable, name=[_], value=[FOO]
$ ./bash --noprofile --norc -c 'declare FOO=bar'
lastword=[declare]
lastarg=[FOO=bar]
bind_variable, name=[FOO], value=[(null)]
before bind_lastarg, lastarg=[FOO=bar]
bind_lastarg, arg=[FOO=bar]
bind_variable, name=[_], value=[FOO=bar]
Vous pouvez voir que l' analyseur voit le dernier argument attendu ( lastarg=) dans tous les cas, mais ce qui se passe ensuite dépend de ce que bash pense que cela devrait se produire. Voir execute_cmd.c, execute_simple_command () .
Dans le cas de export FOO=bar, bash effectue l'affectation puis exporte la variable. Cela semble cohérent avec l'affirmation de la documentation selon laquelle le dernier argument a été calculé après l'expansion.
EDITORest un argument pour exporter