![bash 中的历史扩展何时发生?](https://linux22.com/image/133767/bash%20%E4%B8%AD%E7%9A%84%E5%8E%86%E5%8F%B2%E6%89%A9%E5%B1%95%E4%BD%95%E6%97%B6%E5%8F%91%E7%94%9F%EF%BC%9F.png)
历史扩展什么时候发生?
来自 bash 手册
将字符括在双引号 ('"') 中会保留引号内所有字符的字面值,但 '$'、'`'、'\' 和启用历史扩展时的 '!' 除外。
由于解析器在解析阶段识别双引号,因此解析后必须进行历史扩展是否正确?
如果是,那么 shell 扩展(例如大括号扩展、参数扩展、文件名扩展等)何时发生?
但我认为历史扩展是由shell的readline提供的,所以是在词法分析和解析之前处理的?就像 shell 中的自动完成一样。我错过了什么吗?
谢谢。
答案1
引用bash 手册:
读取完整行后,在 shell 将其分解为单词之前,立即执行历史扩展。
历史扩展是处理的第一阶段,甚至在 shell 解析之前,这就是双引号的原因不protected !
:后者在双引号之前处理。它由历史库处理,历史库实现自己的解析,并有几种保护历史运算符的方法:
只有 '
\
' 和 ''
' 可以用于转义历史扩展字符,但如果历史扩展字符紧接在双引号字符串中的结束双引号之前,则也将其视为带引号的。
当 shell 的解析器开始处理字符串时,它已经被历史库解析并且历史扩展已经发生。
答案2
正如@Stephen Kitt所说,历史扩展应该在第一阶段完成。这种模式可以通过以下事情来理解:如果我们输入任意 bash 代码,例如
echo "the value of a is $a" > tmp
然后我们使用use历史扩展,
!-1
很明显,上面的行会再次执行相同的操作。我们应该注意到的是,它将!-1
扩展到echo "the value of a is $a" > tmp
第一个。如果这种扩展发生在解析阶段之后,那么我们应该意识到$a
将无法正确解析,但实际上并没有发生。