经常用Linux都会用到Shell的自动补全功能:输入部分命令,按两个Tab键就可以把完整的命令或路径调出来了。这个功能功能减少了用户的记忆和操 作步骤,可以提高工作效率。但是Shell的强大不仅在于把命令、文件名补全,它还可以自动补全变量、用户名、路径、文件名、路径、服务、job,更方便 的是你可以为自己的命令量身定作一套自己的补全方式。
比如经常使用的tar命令,按tab默认是打印出来所在文件夹下所有的文件,如果可以只打印出来.tar后缀的岂不是更好。那你可以这么做:
complete -f -X '!*.tar*' tar
效果如下:
complete比较常用的参数为:
-c: 补全的对象是Linux下的命令
-f:补全的对象是文件
-d:补全的对象是目录
-X:对补全的对象进行正则过滤
-F:如果上面这些还满足不了你的要求,就可以使用该参数了,它主要是通过使用自定义函数来为你的脚本制定补全规则。
我有一个脚本viewlog,它的参数是
viewlog -s servicename -t logtype
其中servicename为 /data/applog目录下的文件名,logtype为debug error key perform run中的一种。
想实现的效果是:输入viewlog时可以自动补全出-t -s , 输入-s时可以自动补全出/data/applog下的文件,-t时则可以自动补全出debug error key perform run中的一种
这就要用到complete中的-F参数了。
其实Bash_complete的工作依赖两个内置函数,complete和compgen,
Complete指定每个参数依赖什么样的规则来补全;
Compgen则根据complete的规则来生成符合规则的补全对象。
Compgen的使用方法是:
compgen -W "${opts}" -- ${cur}
上面的opts是所有可能的要补全的参考对象。Cur则是目前已经提供给compgen的字符串,我们来看一个例子。
pengzhanwu@ISD_223_122_sles10_64:~/complete> compgen -W "debug error error2 key perform run" -- "err"
error
error2
可以看到compgen就是把opts中与cur匹配的字符串列出来。
Complete的-F参数需要自己按照你对脚本补全的要求来写一个函数,该函数中默认使用的变量有:
COMPREPLY: 是一个数组,里面包含的是补全匹配的结果
COMP_WORDS:一个包含在命令行中输入的字符串的数组
COMP_CWORD:COMP_WORDS数组中的下标。
以下为脚本_viewlog的内容:
_viewlog()
{
local cur prev opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
opts="-s -t"
#参数-s需要补全/data/applog目录下的服务
if [[ ${prev} == "-s" ]]
then
local servicename=$(ls -l /data/applog | grep ^d | awk '{print $9}')
COMPREPLY=( $(compgen -W "${servicename}" -- ${cur}) )
return 0
fi
#-t的补全对象为"debug error key perform run"
if [[ ${prev} == "-t" ]]
then
local logtypes="debug error key perform run"
COMPREPLY=( $(compgen -W "debug error key perform run" -- ${cur}) )
return 0
fi
#只输入viewlog时,补全该命令可选的参数
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
}
complete -F _viewlog viewlog
需要把脚本文件复制到/etc/bash_completion.d目录上,理论上放到该目录下即可自动加载,但是我这边好像不行。所以仍然需要在
sudo echo ". /etc/bash_completion.d/viewlog_complete" >>/etc/profile.d/complete.bash
最终效果如下: