回响着“!”字符串内部做了一些奇怪的事情

回响着“!”字符串内部做了一些奇怪的事情

如果我输入:

echo "Hello, World!"

我不知道它的名字,但它提示我输入下一行。你知道这PS2件事。或者,如果您键入echo \并按Enter

为什么?

嗯,我知道那!是一个特殊变量您可以用它参考您的历史记录。

但一旦我使用这个:

echo "Hello, World"!

我得到了我想要的输出。发生了什么事,为什么不能!在内部使用""


感谢您的帮助 :)

答案1

!不是特殊的_变量。 (有一个名为 的变量!,您可以使用 访问它$!,但它是不相关的。)它是一个具有特殊含义的字符,具体取决于 bash 在哪里看到它以及后面的内容。

角色!开始历史扩展。 Bash 在解析命令行时,当它以交互方式读取命令时(不是在运行脚本时,甚至是来自交互式命令行的脚本),很早就执行历史.扩展source。您可以设置变量histchars选择不同的字符代替!(但大多数其他 ASCII 字符会与常见用法发生冲突)。

人物! 开始历史替换

除非后面跟有空格、制表符、行尾、“=”或“(”(当使用内置 shopt 启用 extglob shell 选项时)。

echo "Hello, world"!所以像or 之类的事情if ! grep -q foo myfile; …不会触发任何历史扩展。

单引号美元单引号防止历史扩展(即历史扩展字符在 内时没有其特殊含义'…'),并且引用字符的反斜杠可以保护该字符免于启动历史扩展,但是双引号不,除了(从 bash 4.4 开始),当 bash 在 POSIX 兼容模式下调用时。也就是说,默认情况下,

echo "!foo"

制作!foo一个历史参考,该参考被替换在双引号内。您不能简单地在双引号字符串中包含实际的感叹号,因为其中echo "\!foo"会包含反斜杠。你必须使用类似echo \!"foo"或 的东西echo '!foo'。我不知道 bash 为何这样做:这是 20 世纪 80 年代做出的设计决策。 (Bash 从 csh 继承了历史扩展,但情况更糟:即使是单引号也不能防止历史扩展。)

但我无法重现这个确切的情况:

bash-5.0$ echo "Hello, World!"
Hello, World!

但这可能取决于 bash 的版本或配置。双引号本身并不会抑制历史扩展:事实上,它!"不适合任何形式事件指示符

bash-5.0$ echo "Hello!world"
bash: !world: event not found`

答案2

假设您使用bashas 标记,请使用单引号而不是双引号

echo 'Hello, World!'
Hello, World!

不过,我认为您更有可能使用zsh,并且适用相同的修复:

echo "Hello, World!"
dquote>

echo 'Hello, World!'
Hello, World!

shell 中的 "..."、'...'、$'...' 和 $"..." 引号之间有什么区别?有关不同类型的报价以及何时(不)使用它们的更多信息。

相关内容