为什么双引号内的感叹号会导致Bash错误?
请看这些命令:
$ notify-send SYNC TIME! $ notify-send 'SYNC TIME!' $ notify-send "SYNC TIME!" bash: !": event not found $
前两个命令按预期产生通知气泡。 第三个给出了显示的错误。
和
$ echo SYNC TIME! SYNC TIME! $ echo 'SYNC TIME!' SYNC TIME! $ echo "SYNC TIME!" bash: !": event not found $
在这里, echo
适用于前两个命令,但不适用于第三个命令。
这里有更多的问题(虽然我没打算使用它):都notify-send "SYNC!TIME"
和echo "SYNC!TIME"
给bash: !TIME": event not found
。
但是notify-send
和echo
都与"SYNC! TIME"
有人可以解释为什么bash: !": event not found
错误?
!
是Bash中的默认历史记录扩展字符,请参阅Bash联机帮助页中的“HISTORY EXPANSION”部分
-
历史扩张如果不发生
!
用单引号括起来,如notify-send 'SYNC TIME!'
-
历史扩张如果不发生
!
后跟一个空格,制表符,换行符,回车符或=
,如下所示notify-send SYNC TIME!
-
历史扩张确实发生在
echo "SYNC TIME!"
因此,如果在历史记录中没有以
"
以"
开头的命令,则会出现错误
因为在bash中!
是一个保留字(OK,character),它在不同的上下文中具有特殊含义。 在这种特殊情况下,你在历史搜索中与其重要性相悖。 来自man bash
:
History expansions introduce words from the history list into the input stream, making it easy to repeat commands, insert the arguments to a previous command into the current input line, or fix errors in previous commands quickly. [...] History expansions are introduced by the appearance of the history expansion character, which is ! by default. Only backslash (\) and single quotes can quote the history expansion character.
基本上,这意味着bash将采取后面的角色!
并在历史记录中搜索它找到的第一个以这些字符开头的命令。 演示比解释更容易:
$ echo foo foo $ !e echo foo foo
的!
激活的历史记录扩展,它与以e
开头的第一个命令相匹配,后者是先前运行的echo foo
,然后再次运行。 所以,当你写"SYNC TIME!"
,bash看到了!"
,搜索一个以"
开头的命令的历史"
,失败并抱怨它。 你可以通过运行来获得相同的错误,例如!nocommandstartswiththis
。
要打印感叹号,您需要通过以下两种方式之一来转义它:
echo 'Hello world!' echo Hello world\!