「-bash:!」とは何ですか:イベントが見つかりません」


114

bashシェルで次を実行してみてください echo "Reboot your instance!"

私のインストール:

root@domU-12-31-39-04-11-83:/usr/local/bin# bash --version
GNU bash, version 4.1.5(1)-release (i686-pc-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
root@domU-12-31-39-04-11-83:/usr/local/bin# uname -a
Linux domU-12-31-39-04-11-83 2.6.35-22-virtual #35-Ubuntu SMP Sat Oct 16 23:57:40 UTC 2010 i686 GNU/Linux
root@domU-12-31-39-04-11-83:/usr/local/bin# echo "Reboot your instance!"
-bash: !": event not found

「bashイベント」とは何ですか?この概念を聞いたことがありません。また、「!」をどのように出力する必要がありますか 文の終わりに?

回答:


53

を使用して履歴置換をオフにできますset +H


2
構文の背後にある理由を知っていますか?それは本当に直観に反するようです。+H何かを有効にし、何か-Hを無効にするために入力すると思うでしょう。
ギャビン区

7
@PunkyGuy:その背後にある履歴(わざと意図)がわかりませんが、Unixオプションは通常ハイフン(またはマイナス)で始まり、+単にその反対です。
デニスウィリアムソン

105

!bashの特殊文字であり、前のコマンドを参照するために使用されます。例えば、

!rm

文字列「rm」で始まる最後のコマンドを呼び出して実行します。

!rm:p

文字列「rm」で始まった最後のコマンドを呼び出しますが、実行しません。bashは、感嘆符を感嘆符の直後の文字で始まる最後のコマンドをここで置き換えるecho "reboot your instance!"」と解釈し、単一の文字で始まる履歴(イベント)を見つけることができないと不平を言っています。ダブルクォート。

試して

echo reboot your instance\!

感嘆符をbashから保護(エスケープ)します。


はい。ただし、echo -e "いくつかのテキスト$ ENV_VALいくつかのテキストを今すぐ再起動してください!" ?
マキシムVeksler

1
2つのエコーステートメントを記述します。あなたは無料で改行を取得します。
MadHatter

1
簡単な解決策は、単一引用符と二重引用符を一度に使用することです:echo -e "Text \ nReeboot" '!'
mmey 14年

4
これはひどい。感嘆符をエスケープしないと、bashは適合をスローします。私は場合はやるそれをエスケープ、バックスラッシュは、最終的な文字列に含まれています。なぜこれをするの、バッシュ!(pastebin.com/g4PYv56A
Hubro

2
@Hubro公平に、私はそれがすべてbashのせいだと確信していません。rubyを使用してbashにフィードすることにより、多少複雑な問題が発生します。エスケープ文字の除去または強化においてrubyがどの部分を果たしているかは明確ではありません。
マッドハッター

25

元の問題を解決するには、二重引用符ではなく一重引用符を使用してみてください。後者の場合、bashは結果をコマンドに渡す前に特定の文字を展開しようとします(この場合はエコー)。単一引用符を使用すると、bashは文字列全体を変更せずに渡します。

!コマンドラインの履歴を参照するためにコマンドで使用されます。完全なセットについては、http//tldp.org/LDP/abs/html/abs-guide.html#HISTCOMMANDSを参照してください。上記の例では、bashは、!"エコーが表示される前にイベントへの参照として展開しようとしているため、エラーが発生します。

スクリプトでは、対話型シェルでのみ意味があるため、履歴コマンドはすべて無効になっていることに注意してください。

私が定期的に使用している唯一のものは!$です。前のコマンドの最後の引数に展開されます。それは場所で便利な速記です。


4
!!最後に入力したコマンドをすべて入力することは非常に便利です。特に、sudo !!またはpfexec !!
jgoldschrafe

2
sudoとpfexecも素晴らしいユーティリティであると思いますが、それほど熱心である必要はありません。
LeartS 14

$_はbashよりも多くのシェルで動作し、とは異なり適切な変数です!$。(および@LeartS:私はあなたのジョークの絵文字の欠如が好きでした。;))
ΤΖΩΤΖΙΟΥ16年

7

間にスペースを入れてください!そして「それは動作しますよりも。

乾杯。


2
ソリューションが機能する理由について説明してください。
200_success 14

2
これは、Bashが処理するだけなので機能します!空白以外の文字が直接続く場合は、特殊文字として。それは、常に希望されない場合がありますので、しかし、それはまた...、あなたの出力に余分な空白が追加されます
mmey

2

はい、 !bashの特殊文字であり、前のコマンドを参照するために使用されます。

状況に対処できる方法はほとんどありません

以下は、文字列をそのまま出力します

echo 'Reboot your instance!'

以下はコマンドを実行し、文字列を連結します

echo 'escaping #'" adding `which python` to the string"
echo '#!'`which python`

1

bash 4.3、それはそうです、あなたは、もはや単一引用符またはを使用する必要がありませんset +H

$ bash --version
GNU bash, version 4.3.46(1)-release (x86_64-unknown-linux-gnu)
[...]
$ echo "Reboot your instance!"
Reboot your instance!

おそらくバグです。ここでは、4.4.12を持っているのに、もう一度set +H引用する必要があります。または、set +Hどこかにあります(など/etc/profile)。
ボードーティーセン

文の最後にない!-charを使用すると、bashのイベント検出がまだ正常に機能していることを確認できます。バージョンは4.3.30です........ $ echo "文を再確認してください!foo" bash:!foo:イベントが見つかりません
-JohnnyD92

0

また、heredocを使用することもできます。

cat <<EOF
Reboot your instance!
EOF

この場合、それは1行ではなく、長いコマンド(bashスクリプトの作成など)で機能するため、迷惑です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.