Bash的自动完成功能很爽,它不知道免掉我多少记忆的负担,节约了多少键盘操作。 但是对于我们自己写的脚本也能够利用它的自动完成功能吗?回答是肯定的。下面以几个例子来说明。
程序员需要记忆很多东西,bash, vi, screen, svn都有很多命令和快捷键,偏偏我的记忆力不行,不时查看cheatsheet,每次都cd到某个目录,从一大堆文件中找到那个文件,然后再打开,这个过程显然很烦琐。所以我写了一个脚本,叫做quickref,它接收一个参数,例如bash, vi,然后就会打开对应的cheatsheet。
quickref:
#!/bin/bash
case $1 in
bash)
exo-open ~/dropbox/cheatsheets/bash/bash_cheat_sheet.pdf
;;
vi)
exo-open ~/dropbox/cheatsheets/vi_cheat_sheet.pdf
;;
# more...
esac
exo-open是xubuntu下的命令,它自动用文件关联的应用程序打开, 例如, pdf文件就会用evince打开。ubuntu下对应的命令是gnome-open。
如果只有bash, vi的cheatsheet,一切不成问题,但是当列表越来越长,问题就来,你不知道你的命令能够接受哪些参数,输入命令时你得考虑,我该输入什么呢?可能还得来回折腾几次,最坏的情况,你可能需要查看源代码才能确定你到底能输入什么。你可以将它们显示在出错消息中,这样可以节省一些功夫,但总不太好。我们可以利用Bash的自动完成功能,我不再担心会输入错误。
我们直接来看怎么做,建立一个文件quickref_completion, 输入以下内容:
_quickref_completion()
{
local cur
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=($( compgen -W 'bash vi' -- $cur ))
return 0
}
complete -F _quickref_completion quickref
然后执行命令". quickref_complection",然后再在bash下输入"quickref ",然后再按Tab(或许得按两次Tab),你会发现bash自动列出所有匹配的結果,下面是我的机器上的显示結果:
$ quickref
bash vi
$ quickref
怎么实现的呢?其实很简单,_quickref_completion函数用来完成主要的功能,前三行用来得到用户当前的输入,全部补全的結果放在COMPREPLY数组中。这里补全的功能由compgen命令来完成,它完成的功能就是从单词列表中选出匹配给定前缀的所有单词,你最后在命令行下测试一下:
$ compgen -W "find fine hello"
find
fine
hello
$ compgen -W "find fine hello" fi
find
fine
最后complete命令用来注册自动补全函数,第一个参数就是自动补全的函数,后面的参数是应用这个补全函数的所有命令。执行quickref_completion的操作最好放在bashrc中去。
再一个例子,我经常用到命令"sudo apt-get install"命令,所以我给它定义了一个别名:"alias pkginstall='sudo apt-get install'",但这样不好的是,你不能再利用apt-get install的自动完成功能。另外我也定义了别名"alias pkgremove='sudo apt-get remove", 我为它们写了自动补全的函数:
_pkginstall_completion()
{
local cur
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=( $( apt-cache pkgnames -- $cur ) )
}
complete -F _pkginstall_completion pkginstall
_pkgremove_completion()
{
local cur
COMPREPLY=()
cur=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=( $( dpkg -l | awk '{ print $2 }' | grep "^${cur}" ) )
}
complete -F _pkgremove_completion pkgremove
代码就不再解释了,很简单,至于用到的命令,不熟悉的在命令行下试试就知道了。
当然这里所介绍的只是十分简单,但于我已经够用了,至少到目前为止是这样。但要完成更加复杂的功能,例如对于不同的选项,使用不同的命令完成,例如apt-get install和apt-get remove的自动补全就不一样,你可能需要参考其它文章。/etc/complete.d/目录下有很多补全函数的实现,你可以拿来看一下。也可能参考官方文章
Programmable-Completion.