感嘆符「!」が時々バッシュを台無しにするのはなぜですか?

感嘆符「!」が時々バッシュを台無しにするのはなぜですか?

!コマンドライン履歴の文脈では、これがコマンドラインに特別な意味があることを知っていますが、それ以外にも感嘆符は時々スクリプト実行時に解析エラーを引き起こす可能性があります。
aと関係があるようですが、eventaが何なのかわかりません。イベントそれが何であるか、何をするか。それにもかかわらず、同じコマンドが状況によって異なる動作をする可能性があります。
以下の最後の例ではエラーが発生しますが、同じコードがコマンド置換の外部で動作する場合、なぜ動作しますか? ..GNU bash 4.1.5の使用

# This works, with or without a space between ! and p
  { echo -e "foo\nbar" | sed -nre '/foo/! p'
    echo -e "foo\nbar" | sed -nre '/foo/!p'; }
# bar
# bar

# This works, works when there is a space between ! and p
  var="$(echo -e "foo\nbar" | sed -nre '/foo/! p')"; echo "$var"
# bar

# This causes an ERROR, with NO space between ! and p
  var="$(echo -e "foo\nbar" | sed -nre '/foo/!p')"; echo "$var"
# bash: !p': event not found

ベストアンサー1

この!役割はbashの履歴置換を呼び出します(対話型シェルでデフォルトで有効になっています)。失敗した例のように、文字列が後に続く場合は、その文字列で始まる最後の履歴イベントに拡張しようとします。この$var文字列の値を拡張すると、!echo履歴の最後のechoコマンドまで拡張されます。

スペースは、これらの拡張の破壊的な機能です。まず、これが変数をどのように処理するかを見てください。

# var="like"
# echo "$var"
like
# echo "$"
$
# echo "Do you $var frogs?"
Do you like frogs?       <- as expected, variable name broken at space
# echo "Do you $varfrogs?"
Do you?                  <- $varfrogs not defined, replaced with blank
# echo "Do you $ var frogs?"
Do you $ var frogs?      <- $ not a valid variable name, ignored

歴史拡張でも同じことが起こります。感嘆符(!)は履歴置換シーケンスを開始しますが、後に文字列が続く場合にのみ適用されます。置換シーケンスの一部ではない文字通りの爆発を作成するには、スペースを追加します。

一重引用符を使用すると、これらの変数の置換と履歴の拡張を防ぐことができます。最初の例では一重引用符を使用しているため、正しく機能します。最後の例は二重引用符で囲まれているため、bashは他の操作を実行する前に拡張シーケンスを検索します。最初のものがトリップしない唯一の理由は、上記のように空白が壊れる文字であるためです。

おすすめ記事