为什么当我针对 REST API 运行curl 时,shell 会解释密钥中的特殊字符 (!)?
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'"'"
一行中可以使用多个带引号的字符串。另外,我使用双引号来包裹单引号,以便将它们视为字符串而不是字符串边界标记。
答案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" aa'bb!cc'dd(好的) bash-4.2$ printf '%s\n' "aa'bb"'!'"cc'dd" aa'bb!cc'dd(好的)
也就是说,爆炸必须用单引号或反斜杠转义(双引号不会转义它们)。双引号内的反斜杠将阻止历史扩展,但反斜杠将保留。
在这方面,bash
行为不同于(t)csh
(bash
借用了该功能)或删除了如您所期望的zsh
用于转义的反斜杠的行为。!
如果你从不使用历史扩展,你也可以完全禁用它来避免这种麻烦:
set +H
答案4
接下来!
是...东西..在 Bash shell 中意味着从 shell 历史记录中提取值。您可以使用命令查看历史记录history
。这是您之前运行的命令的列表。
要阻止 shell 解释此字符,只需将参数用单引号 ( '
) 括起来或转义!
.在您的情况下,只需转义它就足够了,并删除单引号 ( '
)。
$ curl https://foo.my.salesforce.com/services/data/v28.0/ -H "Authorization: Bearer 00DE0000000K0eM\!AQYAQGgmLxxxxxxxxx"