linux shell 函数,实现自动补全

实例1:

function _bigtool() {
    COMPREPLY=()
    local cur=${COMP_WORDS[COMP_CWORD]};
    local com=${COMP_WORDS[COMP_CWORD-1]};
    case $com in
    'vs')
        COMPREPLY=($(compgen -W 'checkout display remove add' -- $cur))
        ;;
    *)
        ;;
    esac  ##一定要加esac代表case结束
    return 0
}
complete -F _bigtool vs

实例2:

_foo()
{
    local cur=${COMP_WORDS[COMP_CWORD]}
    COMPREPLY=( $(compgen -W "exec help test" -- $cur) )
}
complete -F _foo foo

实例解析

function _abc() {  # 函数声明和函数名,function关键字可以不加  前面第一个字母也不用是_,输入_a可以补全_abc
    COMPREPLY=()   ##声明,候选参数保存在compreply里面
    local cur=${COMP_WORDS[COMP_CWORD]};
    local com=${COMP_WORDS[COMP_CWORD-1]};
    case $com in
    'abc')
        COMPREPLY=($(compgen -W 'build_all compile update' -- $cur))
        ;;
    'compile')
        local pro=($(awk '{print $1}' project.list))
        COMPREPLY=($(compgen -W '${pro[@]}' -- $cur))
        ;;
    *)
        ;;
    esac
    return 0
}
complete -F _abc abc  # 才能生效参数tab自动补全

分割线

详细

  1. 背景
    我们在linux终端操作的时候经常使用tab按键自动补全命令。那么这个是怎么实现的呢?当自己写脚本的时候如何让用户也能自动补全呢?linux提供了两个重要的命令帮助我们实现:
    compgen和complete

  2. complete命令
    用法

[root@localhost ~]# help complete
complete: complete [-abcdefgjksuv] [-pr] [-DE] [-o option] [-A action] [-G globpat] [-W wordlist]  [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [name ...]
complete [-abcdefgjksuv] [-o comp-option] [-DEI] [-A action] [-G globpat]
[-W wordlist] [-F function] [-C command] [-X filterpat]
[-P prefix] [-S suffix] name [name …]
complete -pr [-DEI] [name …]

解释:

就是 complete 补全行为选项 命令名

-F:`执行指定函数名`,候选结果保存在 COMPREPLY 数组变量里,补全功能更强大,可以实现命令参数补全,函数名在 /etc/bash_completion 定义的。
-f:补全文件名,后可跟 -X 参数。
-X:过滤表达式,符合表达式的文件名会被排除,即不会在补全候选显示出来,如果以感叹号开头,则表示反转,即符合表达式的文件名才显示。
-o:补全类型,filenames 表示补全的是一个文件,跟 -f 参数使用才有效;其它值如 dirnames 表示补全目录。

实例:

_lunch() {
    local pre cur opts  #声明局部变量
 
    COMPREPLY=()  #声明一个列表
    pre=${COMP_WORDS[COMP_CWORD-1]} #获取前面的输入的词
    cur=${COMP_WORDS[COMP_CWORD]}  #获取当前输入的词
    opts="-f -r -t -w -o --output -v --version -h --help" #补全选项
    COMPREPLY=( $( compgen -W "$opts" -- $cur ) )
}
complete  -F _lunch  lunch

最后一行“complete _lunch lunch”是实现自动补全功能的关键:
指bash在遇到lunch这个词时,调用_lunch这个函数生成补全内容。(叫_lunch其实只是出于惯例,并不一定要在前面加下划线)。_lunch函数将输入三个参数:要补全的命令名、当前光标所在的词、当前光标所在的词的前一个词,生成的补全结果需要存储到COMPREPLY变量中,以待bash获取。

更新2023.11.7

分割线

1. 基础介绍

  • complete (补全命令)
    complete -F _lunch lunch

  • compgen(筛选命令)
    常用参数

    重点说明: Parameter description
    -W wordlist 分割 wordlist 中的单词,生成候选补全列表

    COMPREPLY=( $( compgen -W "$opts" -- $cur ) )
    在这段代码中,COMP_WORDS是一个包含当前命令行的所有单词的数组,COMP_CWORD是当前光标所在的单词的索引。
    这段代码的作用是将当前光标所在的单词赋值给变量cur。这样做可能是为了在自动补全的功能中使用cur变量来获取当前正在输入的单词,以便进行相应的处理。

2. 实例解析:

自动补全脚本complete_tool.sh :

_service_tool()
{   
   # 参数变量声明
   COMPREPLY=()
   local cur=${COMP_WORDS[COMP_CWORD]}
   local cmd=${COMP_WORDS[COMP_CWORD-1]}    
   case $cmd in    ##对当前输入的命令进行判断
   './odm_tools.sh')
    COMPREPLY=( $(compgen -W '--FirmwareUpgrade --Diagnose --ServerConfigCheck' -- $cur ) )  ##候补选项
   ;;
    
    '--FirmwareUpgrade') ##针对每个候补选项的操作
    COMPREPLY=( $(compgen -W '--AfterReplaceMotherBoard --BiosUpgrade --BmcUpgrade --NicUpgrade --RaidHbaUpgrade --PsuUpgrade' -- $cur ) )
   ;;
    
    '--Diagnose')
    COMPREPLY=( $(compgen -W '--FastTestForAllHardWare --CpuFastTest --MemoryFastTest --RaidHbaFastTest --NicFashTest --BmcFastTest --MemoryFullTest --CpuFullTest --AllLogCollect' -- $cur ) )
   ;;
    
    '--ServerConfigCheck')
    COMPREPLY=( $(compgen -W '--GetALLInfo --GetCpuInfo --GetMemoryInfo --GetHardDiskInfo --GetRaidHbaInfo --GetNicInfo --GetPsuInfo' -- $cur ) )
   ;;
   esac
    return 0
}
complete -F _service_tool ./odm_tools.sh

注意:关于自动tab补全脚本只能实现补全,不能执行相关命令,命令要放在另外的函数
补充case用法:
case语句中,你可以在每个模式下执行多条命令,只需要把它们放在花括号 {} 中。下面是一个示例:

#!/bin/bash
echo "请输入一个选项(A、B、C):"
read option
case $option in
    A)
        {
            echo "你选择了选项A"
            echo "这是选项A的第一条命令"
            echo "这是选项A的第二条命令"
        }
        ;;
    B)
        {
            echo "你选择了选项B"
            echo "这是选项B的第一条命令"
            echo "这是选项B的第二条命令"
        }
        ;;
    C)
        {
            echo "你选择了选项C"
            echo "这是选项C的第一条命令"
            echo "这是选项C的第二条命令"
        }
        ;;
    *)
        echo "输入错误"
        ;;
esac

推荐用法

利用complete补全命令,真正的实现放在autotab函数里,通过$@获取所有的输入,然后再执行命令

function autotab() {
    echo "function autotab called $@"
}
autotab_list=("aa" "bb" "cc" "dd" "123")
function _autotab() {
    local cur
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
	##必须加case
	case $cur in
	"autotab")
    	COMPREPLY=( $(compgen -W "${autotab_list[*]}" -- ${cur}) );;
	esac
    return 0
}
complete -F _autotab autotab

希望这个例子能够帮助你理解在case语句中执行多条命令的方法。如果你有其他问题或需要更多的例子,请随时告诉我!

参考资料

http://www.blogjava.net/sean/archive/2009/06/01/279316.html
https://blog.csdn.net/wwwlyj123321/article/details/122399795
shell脚本自动补全
推荐用法

posted @ 2023-11-06 13:48  学不会xuebuhui  阅读(635)  评论(0编辑  收藏  举报
Language: javascript