如果我输入这个:
echo "Hello, World!"
它会显示继续提示 ( PS2
),类似于键入echo \
然后按Enter。
为什么会这样?我知道这!
是一个特殊变量,您可以使用它来参考您的历史记录。但是,我输入的是
echo "Hello, World"!
我得到了我想要的输出。
发生了什么,为什么不能使用!
inside ""
?
如果我输入这个:
echo "Hello, World!"
它会显示继续提示 ( PS2
),类似于键入echo \
然后按Enter。
为什么会这样?我知道这!
是一个特殊变量,您可以使用它来参考您的历史记录。但是,我输入的是
echo "Hello, World"!
我得到了我想要的输出。
发生了什么,为什么不能使用!
inside ""
?
!
不是一个特殊的_variable。(有一个名为 的变量!
,您可以使用 访问它$!
,但它是不相关的。)它是一个具有特殊含义的字符,具体取决于 bash 看到它的位置和后面的内容。角色
!
开始历史扩张。Bash 在解析命令行时,在交互式读取命令时(不是在运行脚本时,甚至是来自.
交互式source
命令行的脚本)很早就执行历史扩展。您可以设置变量histchars
以选择不同的字符而不是!
(但大多数其他 ASCII 字符会与常用用法冲突)。角色
!
开始历史替换所以喜欢
echo "Hello, world"!
或if ! grep -q foo myfile; …
不触发任何历史扩展的事情。此外,单引号和美元单引号可以防止历史扩展(即历史扩展字符在 内时没有其特殊含义
'…'
),并且引用字符的反斜杠可以防止该字符开始历史扩展,但双引号不会,除了(自 bash 4.4 起)在 POSIX 兼容模式下调用 bash 时。也就是说,默认情况下,制作
!foo
一个历史参考,该参考被替换在双引号内。您不能简单地在双引号字符串中包含实际的感叹号,因为echo "\!foo"
会包含反斜杠。你必须使用类似echo \!"foo"
or的东西echo '!foo'
。我不知道 bash 为什么这样做:这是 1980 年代做出的设计决定。(Bash 从 csh 继承了历史扩展,但更糟的是:即使是单引号也不能防止历史扩展。)我无法重现这个确切的案例:
但这可能取决于 bash 的版本或配置。双引号本身不会抑制历史扩展:事实是
!"
不适合任何形式的事件指示符。假设您使用的
bash
是标记,请使用单引号而不是双引号不过,我认为您更有可能使用
zsh
,并且适用相同的修复方法:请参阅shell 中“...”、“...”、$“...”和 $“...”引号之间的区别是什么?有关不同类型的报价以及何时(不)使用它们的更多信息。