我正在研究 readline 函数shell-expand-line
和alias-expand-line
.来自文档:
shell 扩展行像 shell 一样展开该行。这将执行别名和历史扩展以及所有 shell 单词扩展(参见 Shell 扩展)。
我对此的理解是,它将shell-expand-line
在实际执行点之前执行 bash 所执行的所有替换和扩展。
一个人为的例子似乎支持这一点:
$ NAME="Adam"
$ alias ec='echo'
$ ec $NAME
如果我执行该函数,则shell-expand-line
前一个命令将扩展为$ echo Adam
.
我的困惑始于以下示例:
$ alias cdspace='cd ~/path\ with\ spaces'
$ cdspace
根据我的理解,如果我要执行shell-expand-line
该命令将扩展到$ cd /Users/Adam/path\ with\ spaces
.然而在实践中它扩展到$ cd ~/path with spaces
.cdspace
按原样执行或alias-expand-line
按预期工作,但是如果我通过shell-expand-line
执行扩展它会失败。
在前面的扩展之后,所有不是由上述扩展之一产生的未加引号的字符 '\'、''' 和 '"' 的出现都将被删除。
所以看起来未加引号的反斜杠总是被删除。为了测试这一点,如果我手动键入$ cd ~/path\ with\ spaces
然后执行,shell-expand-line
它将命令更新为$ cd ~/path with spaces
.此外,如果我输入$ cd ~/path\\ with\\ spaces
然后执行shell-expand-line
两次,每次执行都会删除一组反斜杠。
我的期望是将该shell-expand-line
行完全扩展到 bash 内部最终解决的问题,但情况似乎并非如此,因为它需要多次执行。
我现在最终感到困惑的是,$ cd ~/path\ with\ spaces
根据我对Shell 扩展文档,最终会得到解决$ cd ~/path with spaces
。
答案1
我认为 bash 文档在这里不清楚。正如另一条评论中指出的,该shell-expand-line
文档暗示全部当显然不执行波浪号扩展时,将执行 Shell 扩展。
此外,引号删除步骤不会删除在第一组模式匹配后仍然存在的未加引号的反斜杠,这与 3.5.9 (https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Quote-Removal) 表示。
也就是说,我不认为shell-expand-line
它的目的是生成一个可以从 shell 运行的命令(如果这是您所期望的)。因为它正在执行所有 Shell 扩展,假设输入有已经被标记化后,模式匹配步骤将删除反斜杠,使之前转义的空格“未转义”。如果您尝试运行结果字符串,它将被标记化再次,因此每个空格分隔的单词将被视为一个单独的标记。