前のコマンドの最後のパラメータは何でしたか?

前のコマンドの最後のパラメータは何でしたか?

$_前のコマンドの最後のパラメーターと呼ばれます。

それでは、なぜならないのだろうか。EDITOR="emacs -nw"しかし、EDITOR以下の例では?

"emacs -nw"なぜ最後のパラメータの一部ではないのですか?

より一般的には、1つのパラメータと最後のパラメータの定義は何ですか?

ありがとうございます。

$ export EDITOR="emacs -nw"
$ echo $_
EDITOR

答え1

変数の割り当てが引数として許可されると(alias、、、、および使用)、Bashは他のものよりも先に変数の割り当てを処理します(またはむしろ他のものよりも先に認識します。拡張は変数declareの値への割り当てに適用されます)。単語拡張を行うときは、残りのコマンドはなのでに設定します。exportlocalreadonlytypesetexport EDITOR_EDITOR

通常、パラメータは拡張後に残る「単語」です(変数の割り当てとリダイレクトを除く)。

バラより簡単なコマンド拡張詳細については、Bashマニュアルを参照してください。

答え2

重要な要約:の場合、export FOO=barbashは一時環境の作成を呼び出し、その環境を設定して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=barbashは割り当てを実行して変数をエクスポートします。これは、拡張後に最後のパラメータが評価されるという文書の主張と一致するようです。

答え3

タイトルの質問に答えるには、以下を試してください!$

$ export EDITOR="emacs -nw"
$ echo !$
EDITOR=emacs -nw

これは歴史の拡大です。 Bashのマンページから:

履歴拡張は、シェルが行を単語に分割する前に行全体を読み取った直後に行われます。 2つの部分に分かれています。 1つ目は、交換中に使用する履歴リストの行を決定することです。 2番目は、現在の行に含める行の一部を選択することです。履歴で選択した行がイベントで、行で実行された部分が単語です。

...

イベントインジケータ

...

!後に空白、改行、キャリッジリターン、=、または((組み込みのshoptを使用してextglobシェルオプションが有効になっている場合)がない場合は、履歴の交換を開始します。

...

!!前の命令を参照してください。これは「!-1」の同義語です。

...

単語インジケーター

...

$最後の文。これは通常最後の引数ですが、行に単語が1つしかない場合は0番目の単語に展開されます。

...

イベントを指定せずにワード指定子が指定された場合、前のコマンドがイベントとして使用されます。

関連情報