web-dev-qa-db-ja.com

$ _と!$の違いは何ですか?

私はいつも!$を使用して、前のコマンドの最後の引数を参照していました。

例えば.

~/dir » mkdir birthday
~/dir » cd !$
~/dir » cd birthday

しかし、チュートリアルで$_の代わりに!$が使用されているのを見始めました。

2つをテストしましたが、気付いた唯一の違いは微妙ですが、$_はコマンドを評価して実行するのに対し、!$はヒットする前に出力をサニティチェックできるようです。 Enter、しかしこれが$_!$の唯一の違いですか?

更新:重複としてフラグが立てられましたか?この質問は、提案された質問に対して受け入れられた回答によって回答される場合がありますが、それは、回答が必要な質問よりも詳細であるためです。

_ $はどういう意味ですか?を検索すると、提案された重複が生成されますが、!$が何をしたかを尋ねる前に、私はすでに知っていました。その質問が他の質問にも答える可能性があることを示唆するものは何もありません。質問。

4
Luke

man bash、セクション特殊パラメータを検索します。 _の場合、次のようになります。

前のコマンドの最後の引数に展開します(展開後)。

したがって、コマンドラインコンテキストでの違いは拡張です。たとえば、変数FOOを 'bar'に設定し、echo $FOOを実行すると、次の行で$_が実行され、次の行でbarが送信されます。 !$の間にコマンドを実行すると$FOOになります。

この動作はデフォルトでは明白ではないかもしれませんが、shopt -s histverifyを使用するともう少し明白になります。 (histverifyを有効にすると、Bashは直後に履歴拡張を送信しません Enter、最初にコマンド、拡張後を表示し、1秒待ちます Enter)。したがって、FOO=barの後に次のようなものが表示されます。

$ echo $FOO
bar
$ ls !$ $_
# We hit Enter and then see
$ ls $FOO $_ 

$_は、パラメーターの展開中にコマンドが送信されるまで展開されません($FOOとともに)。それは微妙な違いですが、そこに行きます。

おそらく、より興味深い/有用な区別は、$_が変数であるということです。したがって、たとえば、最後のパラメータが/some/file/path.txtの場合、長さ${#_} -> 19を取得し、ファイル名のみ${_##*/} -> path.txtを抽出し、ルート${_//some/other} -> /other/file/path.txtを変更します。 !$ですべてを行うことはできません。


$_は、他のコンテキストでは異なる意味を持つことに注意してください。

シェルの起動時に、環境または引数リストで渡されたとおりに実行されているシェルまたはシェルスクリプトを呼び出すために使用される絶対パス名に設定します。

...そして...

また、実行され、そのコマンドにエクスポートされた環境に配置された各コマンドを呼び出すために使用される絶対パス名に設定します。

...そして...

メールをチェックする場合、このパラメータは現在チェックされているメールファイルの名前を保持します。


PDATE:ほぼ正確ですが、私の答えにはいくつかの重要な情報が欠けており、$_が実際に値を取得する方法/時期について誤解を招く可能性さえあります。その最初の引用は次のように読むことを意図しています:

そのコマンドによって受信されたとき、つまりシェル拡張を実行した後、前のコマンドの最後の引数に展開されます

説明するための最良の方法は、いくつかの例を使用することです。

$ echo "$(date +%s)" # %s is seconds since Epoch
1536984661
$ echo $_  "$(date +%s)" # don't hit enter until a few seconds pass
1536984661 1536984665

したがって、$_は、最初のechoが実行されたときに計算された実際の秒数を取得します。2番目のdate呼び出しの1536984665に近いものではありません。

もう1つ:

$ foo='a b c'
$ echo "$foo"
a b c
$ echo "$_"
a b c
$ #---------
$ echo $foo
a b c
$ echo "$_"
c

2番目のケースでは、$fooを引用しませんでした。 echoに渡される前に、変数/パラメーターの展開とそれに続くWordの分割が行われました。引用符がないため、「a」、「b」、「c」が3つの別々のパラメータとして渡され、$_が最後の「c」を取得しました。

7
B Layer