本帖最后由 Killoser 于 2022-9-21 11:01 编辑

本文分享自华为云社区《有用的 Linux Bash_Completion 命令示例(Steroids 上的 Bash 命令行补全)》,作者:Tiamo_T 。
在 Linux 中,在键入命令时,如果按两次 TAB,它将列出所有以键入字符开头的可用命令。
这不是什么新鲜事,可能你已经知道了。此功能称为 bash 完成。默认情况下,基本文件和目录名称补全在 bash 命令行中可用。
但是,我们可以对这个 bash 补全进行加速,并使用 complete 命令将其提升到一个新的水平。
本教程解释了我们如何使用可编程完成将自动完成应用于选项和命令的参数。
例如,在输入 write 命令后,如果按两次 tab,自动补全会提供用户列表来执行 write 操作。
$ write [TAB][TAB]
  • bala      raj
  • jason     randy
  • john      ritu
  • mayla thomas
  • nisha     www-data
  • 复制代码
    在以下示例中,它将显示 telnet 命令的可用主机名:
    $ telnet [TAB][TAB]
  • localhost  dev-db  fileserver
  • 复制代码
    要在终端中获得可编程完成,您只需要运行 /etc/bash_completion ,如下所示,  
    # . /etc/bash_completion
    复制代码
    还可以取消注释 /etc/bash.bashrc(来自 ubuntu linux 13.04)中的以下行,这样您就不必显式运行上述命令,  
    enable bash completion in interactive shells
  • if ! shopt -oq posix; then
  • if [ -f /usr/share/bash-completion/bash_completion ]; then
  • . /usr/share/bash-completion/bash_completion
  • elif [ -f /etc/bash_completion ]; then
  • . /etc/bash_completion
  •   fi
  • fi
  • 复制代码
    如果你没有找到这些行和 /etc/bash_completion 文件,那么你只需要通过 apt-get 安装名为 bash_completion 的包

    1. 查看现有的 bash-completion
    启用可编程 bash 完成后,定义了一组 bash 完成。命令 complete 用于定义 bash 完成。
    要查看现有的 bash 完成,请使用如下所示的 complete 命令。
    complete -p | less
  • 复制代码
    在上面的示例中,选项 -p 是可选的。

    2. Bash 标准补全列表
    Bash 默认为 Linux 用户提供以下标准补全。

    • 变量名完成
    • 用户名完成
    • 主机名完成
    • 路径名完成
    • 文件名完成
    我们在之前的 bash 标准完成文章中讨论了这些内容。

    3. 定义获取命令的完成
    使用 -c 命令定义完成以获取可用命令列表作为参数。在以下示例中,完成是为哪个命令定义的,
    $ complete -c which
  • $ which [TAB][TAB]
  • Display all 2116 possibilities? (y or n)
  • 复制代码
    如上所示,通过按 “y”,所有命令将被列出。

    4. 定义获取目录的完成
    使用选项 d,可以将完成定义为仅获取目录名称作为参数。在以下示例中,为 ls 定义了完成,
    $ ls
  • countfiles.sh  dir1/          dir2/          dir3/
  • $ complete -d ls
  • $ ls [TAB][TAB]
  • dir1/          dir2/          dir3/
  • 复制代码
    如上所示,按 Tab 仅显示目录。

    5. 定义获取后台作业名称的完成
    使用完成,还可以获取作业名称作为命令的参数。选项 j 用于将作业名称作为参数传递给命令作业,如下所示,  
    $ jobs
  • [1]-  Stopped                 cat
  • [2]+  Stopped                 sed 'p'
  • $ complete -j ./list_job_attrib.sh
  • $ ./list_job_attrib.sh [TAB][TAB]
  • cat   sed
  • 复制代码
    谈到后台作业,您还应该知道如何使用这些示例管理 Linux 后台作业。

    6. 前缀和后缀补全
    可以使用要添加的所需前缀和要附加实际完成的后缀来定义完成。在以下示例中,为 list_job_attrib.sh 定义了前缀和后缀,
    $ jobs
  • [1]+  Stopped                 cat
  • $ complete -P '">' -S '<"' ./list_job_attrib.sh
  • $ ./list_job_attrib.sh [TAB][TAB]
  • $ ./list_job_attrib.sh ">cat<"
  • 复制代码
    7. 文件名和目录完成与排除
    考虑脚本完成运行,输出被写入输出目录,如下所示
    $ cd output/
  • $ ls
  • all_calls.txt   incoming_calls.txt   outgoing_calls.txt   missed_calls.txt
  • parser_mod.tmp extract.o
  • 复制代码
    在上面,如果您需要忽略 .tmp 和 .o 文件以使用 ls 命令自动完成,那么,  
    $ export FIGNORE='.tmp:.o'
  • $ complete -f -d ls
  • $ cd output
  • $ ls [TAB][TAB]
  • all_calls.txt   incoming_calls.txt   outgoing_calls.txt   missed_calls.txt
  • 复制代码
    FIGNORE 是包含文件名后缀的 shell 变量,这些后缀在自动完成中被排除。

    8. 通过 IFS 拆分字符串以获得完成值
    可以使用 -W 选项提及单词列表,并使用 IFS 变量中的值进行拆分。然后每个结果单词都被扩展并显示为完成,
    $ export IFS=" "
  • $ complete -W "bubble quick" ./sort_numbers.sh
  • $ ./sort_numbers.sh [TAB][TAB]
  • bubble   quick
  • 复制代码
    如上所述,通过 IFS 分隔符分割字符串后,单词得到扩展,因此也可以将这些作为变量,如下所示,  
    $ echo $SORT_TYPE1
  • bubble
  • $ echo $SORT_TYPE2
  • quick
  • $ complete -W "$SORT_TYPE1 $SORT_TYPE2" ./sort_numbers.sh
  • $ ./sort_numbers.sh [TAB][TAB]
  • bubble   quick
  • 复制代码
    9. 编写你自己的函数来生成完成
    它允许您包含一个函数来定义完成。使用 -F 选项,传递给完成命令的函数名称并被执行以生成完成。例如,函数编写如下所示,
    _parser_options()
  • {
  •   local curr_arg;
  • curr_arg=${COMP_WORDS[COMP_CWORD]}
  • COMPREPLY=( $(compgen -W '-i --incoming -o --outgoing -m --missed' -- $curr_arg ) );
  • }
  • 复制代码
    在上述函数中,

    • COMPREPLY :数组保存按 [TAB][TAB] 后显示的完成结果
    • COMP_WORDS :在命令行上键入的单词数组
    • COMP_CWORD :COMP_WORDS 数组的索引,并且可以在命令行上使用此不同位置的单词进行访问。
    • compgen : -W 保存可能的完成,并根据 $current_arg 选择相应的参数
    文件 parser_option 中存在的此函数的来源如下所示,
    $ source parser_option
  • 复制代码
    将此函数链接到您的解析器脚本,如下所示,  
    $ complete -F _parser_options ./parser.pl
  • $ ./parser.pl [TAB][TAB]
  • -i       --incoming       -o       --outgoing       -m       --missed
  • 复制代码
    如上所示,解析器的选项由函数 _parser_options () 生成。
    注意:查看 /etc/bash_completion 以查看可编程完成的更多功能。

    10. 当主要不生成任何辅助规范时
    如果定义的完成规范没有生成匹配项,则使用 comp-option 来完成 -o 选项提到的完成。
    $ complete -F _count_files -o dirnames ./countfiles.sh
  • 复制代码
    如上所述,完成是用文件 ./countfiles.sh 的 _count_files 函数定义的。如果 _count_files () 函数未生成任何匹配项,则尝试完成目录。  
    $ ls
  • countfiles.sh    dir1/      dir2/      dir3/
  • $./countfiles.sh [TAB][TAB]
  • dir1    dir2    dir3
  • 复制代码