TL; DR: No caso de export FOO=bar, o bash chama sua criação temporária de ambiente, define FOO=barnesse ambiente e gera um comando final de export FOO. Nesse ponto, FOOé considerado o último argumento.
Ah, os muito abusados $_:
($ _, um sublinhado.) Na inicialização do shell, defina o nome do caminho absoluto usado para chamar o shell ou script de shell sendo executado conforme passado na lista de ambiente ou argumento. Posteriormente, expande para o último argumento para o comando anterior, após a expansão. Defina também o nome do caminho completo usado para chamar cada comando executado e colocado no ambiente exportado para esse comando. Ao verificar o correio, este parâmetro mantém o nome do arquivo de correio.
Vejamos algumas variações:
$ 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
Então, vemos três padrões aqui:
- Os comandos invocados no sistema de arquivos, funções e built-ins se comportam como geralmente esperado:
$_é definido como o próprio nome do comando se não houver argumentos, caso contrário, o último dos argumentos apresentados.
- Após definições de função, loops e outras construções lógicas:
$_não é modificado.
- Tudo o resto:
$_está definido como algo não muito esperado; esquisito.
Eu instrumentei o código para fornecer algumas dicas sobre a estranheza.
$ ./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]
Você pode ver que o analisador vê o último argumento esperado ( lastarg=) em todos os casos, mas o que acontece depois depende do que o bash pensa que deve acontecer. Consulte execute_cmd.c, execute_simple_command () .
No caso de export FOO=bar, o bash faz a atribuição e depois exporta a variável. Isso parece consistente com a afirmação da documentação de que o último argumento foi calculado após a expansão.
EDITORé um argumento para exportar