bash 手动输入双引号 (https://www.gnu.org/software/bash/manual/html_node/Double-Quotes.html) 状态:
如果启用,将执行历史扩展,除非出现“!”出现在双引号中的内容使用反斜杠进行转义。 '!' 前面的反斜杠没有被删除。
为什么有一个特殊的案例!
?如果我转义 a $
(例如),反斜杠不会出现在输出中(例如比较echo "\$"
->$
和echo "\!"
-> \!
)。
!
如果我只想要双引号内的文字该怎么办?
我对这个问题的一个限制是我无法轻松地操纵 bash 调用的形式。我的意思是我坚持使用单个双引号字符串执行命令,即
my-command "a string I generate in an external program that may contain !"
我可以控制字符串的生成方式,但我无法在命令行上将其拆分(例如,类似的东西"part1"\!"part2"
对我不起作用。)
答案1
!
用is打印字符串不是当不加引号、用单引号引起来、在 C 字符串内或在脚本内时会出现问题。
$ echo hello\!world 'hello!world' $'hello!world'
hello!world hello!world hello!world
$ echo 'echo "hello!world"' >file
$ bash file
hello!world
该脚本示例是一种特殊情况,其中未设置 histexpand(默认情况下)。因此,禁用 histexpand (set +o histexpand
与shopt -ou histexpand
或简单地相同set +H
)将具有相同的效果并避免历史扩展。
但是,您要求在(默认)交互式 shell 中使用双引号字符串,而不将字符串分成几部分。好吧,那怎么样:
$ a='!'
$ echo "hello${a}world"
hello!world
关于历史为什么?。
为什么有一个特殊的案例!?
因为大部分ascii字符都是不是特别(内部"
):
$ printf '%s\n' "\a\b\c\d\e\f...\z \!\@\#\% \$a \`date\` \\"
\a\b\c\d\e\f...\z \!\@\#\% $a `date` \
相关文字来自man bash
:将字符括在双引号中会保留引号内所有字符的字面值,但 $、`、\ 以及启用历史扩展时的 ! 除外。
这就是双引号内的反斜杠在古代 shell 中的工作方式,并且POSIX 规范反映出:
仅当被视为特殊时,<反斜杠> 后跟以下字符之一时,才应保留其作为转义字符的特殊含义(请参阅转义字符(反斜杠)):
$ ` " \ <换行>
答案2
显然,Bash 没有删除用于转义!
出现在双引号内的反斜杠(以抑制历史扩展),已在错误打击邮件列表。
中提到的这种行为的历史原因你已有的答案确实是 Bash 的开发者和维护者给出的解释。引用 bug-bash切特·雷米的消息:
根据记录,‘!’只能用单引号或反斜杠进行转义。双引号不起作用,因为“!”根据 POSIX.2 规范和传统 sh 行为,不是双引号内特殊处理的字符之一。
来自同一来源,关于如何处理!
双引号内:
您可以使用“set +o histexpand”关闭历史扩展或在双引号外使用反斜杠。请注意,当 shell 不具有交互性时,通常不会启用历史扩展,因此删除脚本中的反斜杠应该不成问题。
(可以在该邮件列表上找到相同声明的一些变体,例如1和2,其中还提到了与C shell的关系)。
如果您无法使用这些解决方案中的任何一个:以下问题的答案中显示了各种解决方法如何回响一声巨响!,例如将 的第一个字符设置histchars
为不太可能使用的字符,或使用同一变量的第三个字符来启动您不希望应用历史扩展的命令。