为什么 bash 会解释我已转义的字符?

为什么 bash 会解释我已转义的字符?

为什么当我针对 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)cshbash借用了该功能)或删除了如您所期望的zsh用于转义的反斜杠的行为。!

如果你从不使用历史扩展,你也可以完全禁用它来避免这种麻烦:

set +H

答案4

接下来!...东西..在 Bash shell 中意味着从 shell 历史记录中提取值。您可以使用命令查看历史记录history。这是您之前运行的命令的列表。

要阻止 shell 解释此字符,只需将参数用单引号 ( ') 括起来或转义!.在您的情况下,只需转义它就足够了,并删除单引号 ( ')。

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

相关内容