18

以下失败,我不明白为什么:

$ echo "#!"

以下也失败并显示相同的错误消息:

$ echo "\#!"

错误信息:

-bash: !": event not found

为什么会失败?应该怎么echo做呢?

4

5 回答 5

21

!字符用于csh-式历史扩展。

如果您不使用此功能,set +o histexpand(aka set +H)会关闭此行为。它对脚本关闭,但通常启用以进行交互使用。set +o histexpand在这种情况下,我个人的建议是通过添加到您的.bash_profile(或者.bashrc如果您没有.bash_profile; 这比我想尝试放入括号更复杂)来永久关闭它。

作为一种解决方法,如果由于某种原因您不能或不想关闭并忘记此遗留csh功能,您可以使用单引号而不是双引号 - 当然,请记住它们的不同语义。例如,如果您需要将引用与变量插值结合起来,您可以更改

echo "#!$SHELL"  # oops, history expansion breaks this

进入

 echo '#!'"$SHELL"

(注意相邻的单引号和双引号字符串;在 shell 完成此操作后,引号将被删除,字符串#!将在变量值旁边输出SHELL,它们之间没有空格)或其他一些常见的解决方法,例如

 printf '#!%s\n' "$SHELL"
于 2012-08-05T11:48:23.040 回答
9

默认情况下,bash 支持csh兼容的历史扩展。

在 bash

echo #!

只会打印一个换行符,作为#开始评论。

echo "#!"

#是以 开头的字符串的一部分"。bash 仍会检查此类字符串是否有特殊字符。 !是一个特殊字符,当且仅当它后跟任何其他文本。

-bash: !": event not found

在这种情况下,bash 期望!"令牌引用 shell 历史中以 开头的上一个命令",但找不到。本身!不会触发此行为:

$ echo \# !
# !

$ echo fee ! fie
fee ! fie

最后,

$ echo !echo

产生两行,第一行由 shell 打印以显示上面的模式如何扩展为:

echo echo '# !'

而第二行只是执行扩展命令的结果: echo # !


另请参阅:历史扩展的Bash 手册

于 2012-08-05T12:06:21.003 回答
5
echo '#!'

基本上,使用双引号 ( ") 又名“弱引用”,Bash 对字符串做了一些古怪的事情,比如变量替换。使用单 ( ') 又名“强引用”,字符串按字面意思表示。

有关引用的更深入解释,请参见此处。

于 2012-08-05T11:50:08.957 回答
4

另一种解决方法可能是在“!”之后放置一个额外的空格。:

# echo "#! "
#!
于 2016-06-10T06:27:08.443 回答
2

在我的情况下,所有命令都在工作。也许你可以指定你的环境。

$ echo "\#\!"
\#\!
$ echo "#!"
echo "#"
#
$ echo "#!"
echo "#"
#
$ echo $BASH_VERSION
3.2.48(1)-release
于 2012-08-05T11:50:19.740 回答