在bash4之后的版本中,bash支持了一个新功能:自动命令补全。
但是默认该功能是无法实现自动补全的,因为并没有对应的脚本去实现自动补全功能,可以通过安装bash-completion软件包解决部分命令的自动补全功能。当然也有部分软件是自带bash completion补全脚本的。
但是如果使用我们自己编写的脚本,则就没有这样的功能了,此时,就需要自己编写一个自动补全脚本了。

基本命令介绍

如果想要编写自动补全脚本,首先就需要了解两个命令:completecompgen
注:这两个都是bash的内置命令。

complete

用于声明指定命令的补全方式
用法:complete [OPTIONS] name [name…]
OPTIONS

  • -A:指定补全操作,可以指定使用一下几种操作

    • alias:列出所有命令的别名(-a)
    • command:列出命令(-c)
    • directory:列出当前工作目录下的目录(-d)
    • file:列出当前工作目录下的文件(-f)
    • service:列出服务名称(-s)
    • signal:列出信号
    • user:列出用户(-u)
    • group:列出组名(-g)
    • variable:列出变量(v)
  • -W wordlist:指定使用wordlist中的字符串进行补全
  • -F funcname:通过指定函数获取字符串列表进行补全
    注:获取字符串列表方式并不是通过return,而是通过变量COMPREPLY。

详细用法查询:man complete

compgen

列出匹配的补全字符串
用法:compgen [OPTIONS] word
OPTIONS
参数与complete相同。

注:如果word关键字开头包含--,例如--help,那么就需要在这个关键字前先添加--,避免与compgen自带的参数混淆。详细用法看下面的脚本。

测试补全脚本

首先自己编写一个脚本,用来充当命令:

# file:~/bin/myscript

#!/usr/bin/bash
# 功能:输出参数

echo $*

方法一:简易补全

首先使用wordlist方式来进行自动补全,直接运行如下命令

complete -W '--help --dir --list-user --list-group' myscript

然后再进行补全测试:

注:该方法只能进行一些简单的关键字进行补全,如果想要补全不同的内容则只能使用方法二

方法二:动态补全

动态补全脚本是通过调用函数的方式来实现的,通过对函数的自定义,可以实现多种多样的功能。
当调用函数时,默认会传递三个变量:

  • COMP_WORDS:当前用户命令行输入内容(以数组形式传递)
  • CMP_CWORD:当前用户正在补全的字符串数组索引
  • COMP_LINE:当前用户命令行内容(字符串形式)

同时,还有三个函数形参:

  • $1:需要补全参数的命令名称
  • $2:需要补全的参数
  • $3:已经补全的参数

还有一个用于返回补全的变量:

  • COMPREPLY:返回需要补全的关键字(以数组形式存放)

首先编写一个动态补全脚本

# file:~/test

#!/usr/bin/bash

function _myscript(){
    if [[ "${COMP_CWORD}" == "1" ]];then
        COMP_WORD="-f -d -cf -cd --current-file --current-directory --file --directory --user --group --help"
        COMPREPLY=($(compgen -W "$COMP_WORD" -- ${COMP_WORDS[${COMP_CWORD}]}))
    else
        case ${COMP_WORDS[$[$COMP_CWORD-1]]} in
            -d|--directory)
                # 提示/etc/目录下的所有目录
                COMP_FILE=$(find /etc/ -maxdepth 1 -type d -print | xargs -n1 basename)
                COMPREPLY=($(compgen -W "${COMP_FILE}" ${COMP_WORDS[${COMP_CWORD}]}))
                ;;
            -f|--file)
                # 提示/etc/目录下的所有文件
                COMP_FILE=$(find /etc/ -maxdepth 1 -type f -print | xargs -n1 basename)
                COMPREPLY=($(compgen -W "${COMP_FILE}" ${COMP_WORDS[${COMP_CWORD}]}))
                ;;
            -cf|--current-file)
                # 提示当前目录下的文件
                COMPREPLY=($(compgen -f ${COMP_WORDS[${COMP_CWORD}]}))
                ;;
            -cd|--current-directory)
                # 提示当前目录下的目录
                COMPREPLY=($(compgen -d ${COMP_WORDS[${COMP_CWORD}]}))
                ;;
            --user)
                # 提示当前系统的所有用户
                COMPREPLY=($(compgen -u ${COMP_WORDS[${COMP_CWORD}]}))
                ;;
            --group)
                # 提示当前系统的所有组
                COMPREPLY=($(compgen -g ${COMP_WORDS[${COMP_CWORD}]}))
                ;;
    esac
    fi
}
# 注册命令补全函数
complete -F _myscript myscript

加载该自动补全脚本

source test

测试补全是否可用

自动加载补全脚本

默认补全脚本是不会加载的,首先需要安装bash-completion软件包,该软件包内有一个脚本用于自动加载补全脚本。

同时需要注意一下安装目录,bash-completion会从三个地方加载自动补全脚本:

  • /usr/share/bash-completion/completions/:有软件自行管理的自动补全脚本,最好不要改动
  • /etc/bash_completion.d/:该目录下可自行添加所需要的自动补全脚本(全局生效)
  • $HOME/.bash_completion:该文件也是自动补全脚本,不过只对当前用户成效,直接将编写的脚本往该文件追加即可。

注:由于这些补全命令都是使用shell语言编写的,所以可以直接添加到/etc/bashrc$HOME/.bashrc文件中也是可以的,并不一定只能安装在上述几个地方中。

参考链接:

本文经「原本」原创认证,作者乾坤盘,访问yuanben.io查询【36TZXLAH】获取授权信息。

最后修改:2021 年 06 月 07 日 12 : 05 PM
如果觉得我的文章对你有用,请随意赞赏