TL; DR: Nel caso di export FOO=bar, bash invoca la sua creazione di ambiente temporaneo, imposta FOO=barin quell'ambiente, quindi produce un comando finale di export FOO. A quel punto, FOOviene preso come ultimo argomento.
Ah, il tanto abusato $_:
($ _, trattino di sottolineatura). All'avvio della shell, impostare sul percorso assoluto usato per invocare la shell o lo script della shell in esecuzione come passato nell'ambiente o nell'elenco degli argomenti. Successivamente, si espande all'ultimo argomento al comando precedente, dopo l'espansione. Impostato anche sul percorso completo utilizzato per richiamare ciascun comando eseguito e inserito nell'ambiente esportato in quel comando. Quando si controlla la posta, questo parametro contiene il nome del file di posta.
Diamo un'occhiata ad alcune varianti:
$ 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
Quindi vediamo tre schemi qui:
- I comandi richiamati dal filesystem, dalle funzioni e dai built-in si comportano come generalmente previsto:
$_è impostato sul nome del comando stesso se non ci sono argomenti, altrimenti l'ultimo degli argomenti presentati.
- Dopo le definizioni delle funzioni, i loop e altre costruzioni logiche:
$_non viene modificato.
- Tutto il resto:
$_è impostato su qualcosa di non del tutto previsto; strano.
Ho elaborato il codice per fornire alcune informazioni sulla stranezza.
$ ./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]
Si può vedere che il parser vede l'ultimo argomento atteso ( lastarg=) in tutti i casi, ma ciò che accade dopo dipende da ciò che pensa bash dovrebbe accadere. Vedi execute_cmd.c, execute_simple_command () .
Nel caso di export FOO=bar, bash esegue l'assegnazione e quindi esporta la variabile. Ciò sembra coerente con l'affermazione della documentazione secondo cui l'ultimo argomento è stato calcolato dopo l'espansione.
EDITORè un argomento da esportare