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自动补全
分割线
详细
-
背景
我们在linux终端操作的时候经常使用tab按键自动补全命令。那么这个是怎么实现的呢?当自己写脚本的时候如何让用户也能自动补全呢?linux提供了两个重要的命令帮助我们实现:
compgen和complete -
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脚本自动补全
推荐用法