eri*_*ork 13 bash echo ubuntu-12.04
以下失败,我不明白为什么:
$ echo "#!"
Run Code Online (Sandbox Code Playgroud)
以下也失败并出现相同的错误消息:
$ echo "\#!"
Run Code Online (Sandbox Code Playgroud)
错误信息:
-bash: !": event not found
Run Code Online (Sandbox Code Playgroud)
为什么会失败?该怎么echo办呢?
tri*_*eee 14
该!角色用于csh风格的历史扩展.
如果您不使用此功能,set +o histexpand(aka set +H)将关闭此行为.它已关闭脚本,但通常启用交互式使用.
作为一种解决方法,您可以使用单引号而不是双引号 - 当然,请记住它们的不同语义.例如,如果需要将引用与变量插值相结合,则可以进行更改
echo "#!$SHELL" # oops, history expansion breaks this
Run Code Online (Sandbox Code Playgroud)
成
echo '#!'"$SHELL"
Run Code Online (Sandbox Code Playgroud)
(注意相邻的单引号和双引号字符串;在shell完成之后,引号将被删除,字符串set +o histexpand将输出到变量的值旁边,.bash_profile它们之间没有空格)或其他一些常见的解决方法就像
printf '#!%s\n' "$SHELL"
Run Code Online (Sandbox Code Playgroud)
默认情况下,bash支持csh兼容的历史记录扩展.
在bash中
echo #!
Run Code Online (Sandbox Code Playgroud)
只会打印换行符,因为它会#开始发表评论.
在
echo "#!"
Run Code Online (Sandbox Code Playgroud)
的#是字符串的一部分开始".对于特殊字符,bash仍会检查此类字符串. !如果后跟任何其他文本,则为特殊字符.
-bash: !": event not found
Run Code Online (Sandbox Code Playgroud)
在这种情况下,bash期望!"令牌引用shell历史记录中以前的命令",但不会找到.所有这些!都不会触发此行为:
$ echo \# !
# !
$ echo fee ! fie
fee ! fie
Run Code Online (Sandbox Code Playgroud)
最后,
$ echo !echo
Run Code Online (Sandbox Code Playgroud)
生成两行,第一行由shell打印,以显示上面的图案如何扩展为:
echo echo '# !'
Run Code Online (Sandbox Code Playgroud)
而第二行只是执行扩展命令的结果:echo#!
echo '#!'
Run Code Online (Sandbox Code Playgroud)
基本上,使用双引号 ( ") 又名“弱引用”,Bash 对字符串做了一些古怪的事情,比如变量替换。单 ( ') 又名“强引用”,字符串按字面意思表示。
有关引用的更深入解释,请参见例如此处。