「!」をエコーすると、文字列内で奇妙なことが起こります。

「!」をエコーすると、文字列内で奇妙なことが起こります。

次のように入力すると:

echo "Hello, World!"

名前が何であるかはわかりませんが、次の行に進むように求められます。あなたはこれを知っていますPS2。またはを入力echo \して押すEnter

なぜ?

まあ、私もそれが一つである!ことを知っています特殊変数これを使用して履歴を参照できます。

しかし、一度これを使用すると:

echo "Hello, World"!

私が望む結果を得る。何が起こっているのか、なぜ!内部的に使用できないのですか""


あなたの助けをいただきありがとうございます:)

答え1

!特別な変数ではありません。 (!でアクセスできるという変数があります$!が関連はありません。) Bashが見る位置と次の内容によって特別な意味を持つ文字です。

キャラクター!スタート歴史的拡張。 Bashは、インタラクティブにコマンドを読み取ると(対話型コマンドラインのスクリプトでもスクリプトを実行するときではありません)、コマンドライン解析の最初に履歴拡張を実行し.ますsource。変数を設定できますhistchars代わりに別の文字を選択してください!(ただし、他のほとんどのASCII文字は一般的な使用法と競合します)。

数値! 記録交換開始

空白、タブ、行末、「=」、または「(」(組み込みのshoptを使用してextglobシェルオプションが有効になっている場合)が続かない限り。

echo "Hello, world"!したがって、またはそのようなものはif ! grep -q foo myfile; …レコード拡張を引き起こさない。

返品アポストロフィそしてドル一重引用符履歴拡張を防止します(つまり、履歴拡張文字は含まれるときに特別な意味はありません'…')。文字を引用するバックスラッシュは、その文字が履歴拡張を開始するのを防ぎます。二重引用符いいえ、除く(バッシュ4.4からスタート)、POSIX互換モードでbashが呼び出される場合。つまり、基本的に

echo "!foo"

!foo二重引用符で置き換えられる履歴参照を作成します。echo "\!foo"バックスラッシュが含まれるため、二重引用符で囲まれた文字列に実際の感嘆符を含めることはできません。echo \!"foo"またはのようなものを使用する必要がありますecho '!foo'。 Bashがなぜこれをするのかわかりません。これは1980年代に作られたデザイン決定でした。 (Bashはcshから履歴拡張を継承しますが、より悪いです。単一引用符でも履歴拡張を妨げません。)

しかし、この正確な状況を再現することはできません。

bash-5.0$ echo "Hello, World!"
Hello, World!

ただし、これはbashのバージョンや設定によって異なります。二重引用符自体はレコードの拡張を抑制しません。実際には!"どの形式にも適していません。イベントインジケータ

bash-5.0$ echo "Hello!world"
bash: !world: event not found`

答え2

タグとして使用する場合は、bash二重引用符の代わりに一重引用符を使用してください。

echo 'Hello, World!'
Hello, World!

しかし、私はあなたが使用する可能性が高いと思い、zsh同じ修正が適用されます。

echo "Hello, World!"
dquote>

echo 'Hello, World!'
Hello, World!

バラよりシェルの「...」、「...」、$'...'、および$"..."引用符の違いは何ですか?さまざまな種類の見積もりとそれを使用する場合(使用しない場合)の詳細情報。

関連情報