TL; DR:の場合export FOO=bar、bashは一時的な環境の作成を呼び出し、その環境に設定FOO=barしてから、最終的なコマンドを生成しexport FOOます。その時点でFOO、最後の引数として取得されます。
ああ、非常に虐待された$_:
($ _、アンダースコア。)シェルの起動時に、環境または引数リストに渡されて実行されるシェルまたはシェルスクリプトを呼び出すために使用される絶対パス名に設定します。その後、展開後、前のコマンドの最後の引数に展開します。また、そのコマンドにエクスポートされた環境で実行および配置された各コマンドを呼び出すために使用される絶対パス名に設定します。メールをチェックするとき、このパラメーターはメールファイルの名前を保持します。
いくつかのバリエーションを見てみましょう。
$ 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
したがって、ここには3つのパターンがあります。
- ファイルシステム、関数、およびビルトインから呼び出されたコマンドは、一般的に予期されるとおりに動作
$_します。引数がない場合はコマンド名自体に設定され、そうでない場合は提示された引数の最後に設定されます。
- 関数定義、ループ、およびその他の論理構造の後:
$_は変更されません。
- その他すべて:
$_まったく予期しないものに設定されます。変。
私は奇妙さへの洞察を提供するためにコードを実装しました。
$ ./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]
パーサーはlastarg=すべての場合に期待される最後の引数()を見ることがわかりますが、その後何が起こるかは、bashが何をすべきと考えるかに依存します。execute_cmd.c、execute_simple_command()を参照してください。
の場合export FOO=bar、bashは割り当てを行ってから変数をエクスポートします。これは、最後の引数が展開後に計算されたというドキュメントの主張と一致しているようです。
EDITORエクスポートの引数です