在 bash 中导出环境变量时自动完成功能不起作用

在 bash 中导出环境变量时自动完成功能不起作用

假设我希望导出一个名为MYPATHholding以下2个路径的环境变量:

  1. /完整/路径/到/fileA
  2. /另一个/完整/路径/到/fileB

所以,我认为应该在 bash 中这样做:

$export MYPATH=/full/path/to/fileA:/another/full/path/to/fileB

我面临的问题是自动完成(Tab键)在命令中写入路径 A 时起作用,但在:自动完成停止工作后,因此在没有自动完成的情况下很难在控制台中写入路径 B。

令人惊讶的是,如果满足以下条件,它就会起作用:

  • 我使用分号而不是冒号,但这无论如何都不是正确的路径分隔符。
  • 我是root用户。

有人可以解释这种行为的原因吗?

  • Bash 版本:GNU bash,版本 4.3.48(1)-release (x86_64-pc-linux-gnu)
  • Bash 完成版本:all/xenial-updates 1:2.1-4.2ubuntu1.1
  • 操作系统版本:Ubuntu 16.04.6 LTS

答案1

您所描述的行为可能是由bash 完成

(以下内容基于该包的当前版本 (2.9),但对于您拥有的 2.1 版本来说也相当准确)。

bash-completion 提供了一组完成规范(比较规范),Readline 库使用它来完成作为 Bash 中命令的参数提供的单词。它们是使用以下定义的complete 内置命令,通常采用以下形式:

complete -F function command

对于export内置函数,该函数_export在 中定义/usr/share/bash-completion/completions/export

当要完成的单词包含(或以 a 结尾)时=_export尝试将其完成(实际上是第一个 右侧的部分=)作为文件或目录名;当要补全的单词不包含 a 时=,它会尝试将其补全为变量名。由于 Readline 库每次遇到变量中列出的一个字符COMP_WORDBREAKS(除非该字符被转义)(通常包括 )时都会启动一个新的完成,因此:在附加到变量值的第一个冒号之后,完成将停止工作,因为此时,重点是,要完成的单词不再包含(或以)a 结尾=。 (顺便请注意,如果您写入并点击 ,
文件/目录名称补全将再次开始工作)。export myvar=/usr/:othervar=Tab

bash-completion 确实有自己的处理特殊情况的机制。例如,:由 compspec for 正确处理scp,它将冒号右侧的内容解释为远程路径。但同样的情况不适用于export

阅读线的默认行为,当未找到当前命令的 compspec 时触发,最终是尝试文件名完成。这就是为什么在未安装 bash-completion 或以其他方式禁用 bash-completion 时完成path2in起作用的原因(请记住每个冒号都会启动一个新的完成)。export var=/path1/:/path2/

那你能做什么呢?您有一些替代方案:

  1. 将功能请求提交至GitHub 上的 bash-completion

  2. 定义您自己的补全函数export
    首先,将 compspec 复制到用户完成文件(该文件可能尚不存在):

    $ cat /usr/share/bash-completion/completions/export >>~/.bash_completion
    

    然后编辑~/.bash_completioncomplete -F _export export改为complete -F _export -o default export.export当 的特定 compspec 没有给出结果时,这指示 Readline 尝试默认完成。

  3. 使用默认补全,而不是 bash-completion 提供的补全。
    添加到您的~/.bashrc

    complete -o default -o bashdefault export
    

    (建议来自bash-completion 的常见问题解答)。缺点是您无法完成变量名称和export选项。

  4. 如果您愿意足够熟悉 bash-completion,请定义您自己的_export函数,如 (2) 中所示,通过编辑提供的函数以使其进行:特殊处理。

相关内容