前のコマンドの最後の引数は何ですか?


12

$_ 前のコマンドの最後の引数と言われています。

だから私はそれがない理由だろうEDITOR="emacs -nw"が、EDITOR次の例の?

なぜ"emacs -nw"最後の議論の一部ではないのですか?

より一般的には、引数の定義と最後の引数は何ですか?

ありがとう。

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

3
shellcheckが変数を割り当てたのと同じ行でエクスポートしないように指示するのも同じ理由だと思います。割り当てが行われ、変数がエクスポートされます。 EDITORエクスポートの引数です
jesse_b

FWIW、pdkshおよびdash割り当てられた値が含まれますが、ksh93動作は同じbashです。
クサラナンダ

zsh:、export FOO=bar; echo $_出力しexportます。
ilkkachu 2018

@Jesse_b全体は最後の引数/オペランド(割り当てられた値を含む)ですexportが、組み込みのユーティリティであるという事実と関係があるかもしれません。
クサラナンダ

ksh:typeset -x FOO=bar次にecho $_出力FOOしますが、Bashではdeclare -x FOO=bar; echo $_出力しFOO=barます。
ilkkachu

回答:


13

bashは(と彼らは引数として許可されているときに、変数の割り当てを処理しaliasdeclareexportlocalreadonly、およびtypeset)、何かの前に( -拡張が変数に割り当てられた値に適用されるかではなく、それが何かする前にそれらを識別します)。単語拡張になると、残りのコマンドはexport EDITORなので_、に設定されEDITORます。

一般的に言えば、引数は展開後に残る「単語」です(変数の割り当てとリダイレクトは含まれません)。

詳細については、Bashマニュアルの単純なコマンド展開を参照してください。


そして、私declareはの動作が私が説明しているものと一致しないことを理解しています...
スティーブン・キット

まあ、それはあまり一貫していません。declare a=b; echo $_プリントa=b; export c=d; echo $_ちょうど印刷しcます。alias名前だけをlocal出力するようですが、一方で引数全体を出力します。またreadonly、名前だけを印刷します。これは、思っていたのreadonlylocal似ているので、少し意外だっ たのdeclareです。
ilkkachu 2018

1
@ilkkachuへー、私も気づきました(上記参照)。exportそして、readonlyで一緒に宣言されているsetattr.defdeclarelocal、及びtypesetで宣言されてdeclare.defalias一人で立っていますalias.def
Stephen Kitt 2018

ありがとう。変数の割り当てが一部のコマンドの引数として使用される場合、(1)「(または、それよりも前にそれらを識別します—変数に割り当てられた値に展開が適用されます)」(2)「単語の展開になると、残りのコマンドはexport EDITORです」とは、展開の前に変数の割り当てが行われるということですか?2つの引用符は互いに矛盾しているようです。
ティム

ありがとう。私は少し混乱しています。変数の割り当てがalias, declare, export, local, readonlyおよびの引数として使用される場合typeset。最初に何が起こりますか?「それが単語の展開になると、残りのコマンドはexport EDITOR"ですが、変数の割り当てEDITOR="emacs -nw"が展開の前に行われることを意味しますか?そうでない場合、残りのコマンドに引数として割り当てが含まれないのはなぜですか?はいの場合、変数に割り当てられた値の拡張は、変数の割り当てを実行する前に行う必要がありますか?
ティム

4

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は割り当てを行ってから変数をエクスポートします。これは、最後の引数が展開後に計算されたというドキュメントの主張と一致しているようです。


1
シェルはメールをチェックしていることをどのようにして知るのですか?
rackandboneman

@rackandboneman確認せずに、MAILCHECK
Jeff Schallerに

2

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

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

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

履歴の展開は、完全な行が読み込まれた直後、シェルが単語に分割する前に実行されます。2つの部分で行われます。1つ目は、置換時に使用する履歴リストの行を決定することです。2つ目は、現在の行に含めるためにその行の一部を選択することです。履歴から選択された行はイベントであり、その行の作用する部分は単語です。

...

イベント指定子

...

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

...

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

...

単語指定子

...

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

...

イベント指定なしでワード指定子が提供された場合、前のコマンドがイベントとして使用されます。


質問のタイトルを文字通りあまりにも取っています。(わかりません、それはお粗末なタイトルです。)コマンド« export EDITOR="emacs -nw"»は2つの単語で構成されています。最初の単語は« export»で、2番目の単語は« EDITOR="emacs -nw"»です。「この場合!_、bash $_が« EDITOR»に設定されているとすると、「前のコマンドの最後の引数に展開する」と言うとき、bashのマニュアルページとBashマニュアルはどういう意味ですか?」履歴展開に関するbashのマニュアルページセクションをコピーして貼り付けることは、特に役立ちません。
G-Manは「Reinstate Monica」と言います
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.