Bashがエスケープされた文字を解釈するのはなぜですか? [コピー]

Bashがエスケープされた文字を解釈するのはなぜですか? [コピー]

REST APIに対してカールを実行すると、シェルがキーの特殊文字(!)を解釈するのはなぜですか?

curl https://foo.my.salesforce.com/services/data/v28.0/ -H "Authorization: Bearer '00DE0000000K0eM!AQYAQGgmLxxxxxxxxxxx'"  
-bash: !AQYAQGgmLxxxxxxxxxx'": event not found

~によるとこれ、一重引用符を使用すると、bashが文字列を解釈できなくなります。

私は解決策として\文字を試しましたが、これはキーを拒否しました。

curl https://foo.my.salesforce.com/services/data/v28.0/ -H "Authorization: Bearer '00DE0000000K0eM\!AQYAQGgmLxxxxxxxxx'"  
[{"message":"Session expired or invalid","errorCode":"INVALID_SESSION_ID"}]

bashがこの文字列を解釈しないようにするにはどうすればよいですか?

答え1

履歴拡張文字は!二重引用符の間でも特別ですが、一重引用符の間では特別な意味を失います。

ここでは二重引用符で囲まれた文字列の中にあります"Authorization: Bearer '00DE0000000K0eM!AQYAQGgmLxxxxxxxxxxx'"。この文字列の一重引用符は、この文字列の一般的な文字であり、特に解釈されません。これには単一引用符で囲まれた文字列はありません。

バックスラッシュを追加すると、履歴拡張は!トリガーされませんが、バックスラッシュ自体はそのまま残ります。だからあなたはheaderで終わりますAuthorization: Bearer '00DE0000000K0eM\!AQYAQGgmLxxxxxxxxx'

ヘッダーが必要な場合は、Authorization: Bearer '00DE0000000K0eM!AQYAQGgmLxxxxxxxxx'次のように指定できます。

curl https://foo.my.salesforce.com/services/data/v28.0/ -H 'Authorization: Bearer '\''00DE0000000K0eM!AQYAQGgmLxxxxxxxxxxx'\'

答え2

文字列全体を二重引用符で囲んだからです!はい解釈(二重引用符は二重引用符を含む文字列として扱われます)。

努力する:

curl https://foo.my.salesforce.com/services/data/v28.0/ -H 'Authorization: Bearer '"'"'00DE0000000K0eM!AQYAQGgmLxxxxxxxxxxx'"'"  

1行に複数の引用符付き文字列を使用できます。また、文字列境界マーカーではなく文字列として扱われるように、二重引用符を使用して一重引用符を囲みました。

答え3

bash-4.2$ printf '%s\n' "aa'bb!cc'dd"
bash: !cc'dd": イベントが見つかりません(悪い)

bash-4.2$ printf '%s\n' "aa'bb\!cc'dd"
aa'bb\!cc'dd(悪い)

bash-4.2$ printf '%s\n' "aa'bb"\!"cc'dd"
ええと!cc'dd(いいね)

bash-4.2$ printf '%s\n' "aa'bb"'!'"cc'dd"
ええと!cc'dd(いいね)

つまり、爆発は一重引用符またはバックスラッシュでエスケープする必要があります(二重引用符はエスケープされません)。二重引用符内のバックスラッシュは履歴の拡張を防ぎますが、バックスラッシュは保持されます。

この点でのbash動作は、(t)csh期待どおりにエスケープに使用されるバックスラッシュを借用またはbash削除することとは異なります。zsh!

履歴拡張をまったく使用しない場合は、完全に無効にすることでこの問題を回避できます。

set +H

答え4

!...もの..Bashシェルでは、シェル履歴から値を抽出することを意味します。コマンドを使用して履歴を表示できますhistory。以前に実行したコマンドのリスト。

シェルがこの文字を解釈しないようにするには、引数を一重引用符(')で囲むか、エスケープするだけです!。エスケープして単一引用符(')を削除するだけです。

$ curl https://foo.my.salesforce.com/services/data/v28.0/ -H "Authorization: Bearer 00DE0000000K0eM\!AQYAQGgmLxxxxxxxxx"

関連情報