内置补全命令

Bash内置两个补全命令,分别是compgen和complete。compgen命令根据不同的参数,生成匹配单词的候选补全列表,例子如下:

monster@monster-Z:~$ compgen -W 'ha hia hoo world' h
ha
hia
hoo

compgen的常用选项是-W,通过-W参数指定空格分隔的单词列表。h即为我们在命令行当前输入的单词,执行完之后会输出候选的匹配列表。

complete命令的参数类似于compgen,但是它的作用是说明命令如何进行补全,例如同样使用-W参数指定候选单词列表:

monster@monster-Z:~$ complete -W 'word1 word2 word3 hello' foo
monster@monster-Z:~$ foo word
word1 word2 word3

当输入"foo w"再按<tab>的时候,会自动补全为"foo word",再此基础上再按<tab>时,会输出最后一行的"word1 word2 word3"

我们还可以通过-F参数指定一个补全函数:

monster@monster-Z:~$ complete -F _foo foo

现在键入foo命令之后,会调用_foo函数来生成补全的列表,完成补全的功能,而这是补全脚本实现的关键所在。

补全相关的内置变量

除了上面的两个补全命令以外,Bash还有几个内置的变量来辅助补全功能:

COMP_WORDS: 类型为数组,存放当前命令行中输入的所有单词

COMP_CWORD: 类型为整数,当前光标下输入的单词位于COMP_WORDS数组中的索引

COMPREPLY: 类型为数组,候选的补全结果

COMP_WORDBREAKS: 类型为字符串,表示单词之间的分隔符

COMP_LINE: 类型为字符串,表示当前命令行输入

例如我们定义如下一个补全函数_foo: (注:declare -p var的意思是显示变量var的值)

monster@monster-Z:~$ function _foo()
> {
> echo -e "\n"
> declare -p COMP_WORDS
> declare -p COMP_CWORD
> declare -p COMP_LINE
> declare -p COMP_WORDBREAKS
> }
monster@monster-Z:~$ complete -F _foo foo

  

假设我们再在命令行下输入以下内容,再按Tab键补全:

monster@monster-Z:~$ foo b

declare -a COMP_WORDS='([0]="foo" [1]="b")'
declare -- COMP_CWORD="1"
declare -- COMP_LINE="foo b"
declare -- COMP_WORDBREAKS="
\"'><=;|&(:"

需要注意的是,补全功能是Bash自带的,并非一定需要Bash-completion包

编写脚本

补全脚本分成两部分:编写一个补全函数和使用complete命令应用补全函数。

一般补全函数都会定义以下两个变量:

local cur prev

其中cur表示当前光标下的单词,而prev则对应上一个单词:

cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"

初始化相应的变量之后,我们需要定义补全行为,即输入什么的情况下补全什么内容,例如当输入-开头的选项时,我们将所有的选项作为候选的补全结果:

local opts="-h --help -f --file -o --output"

if [[ ${cur} == -* ]]; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi

不过在给COMPREPLY赋值之前,最好将它重置清空,避免被其他补全函数干扰

完整的补全函数如下所示:

function _foo() {
local cur prev opts COMPREPLY=() cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
opts="-h --help -f --file -o --output" if [[ ${cur} == -* ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
fi
}

现在在命令行下就可以对foo命令进行参数补全了:

monster@monster-Z:~$ complete -F _foo foo
monster@monster-Z:~$ foo -
-f --file -h --help -o --output

利用号prev变量可以让补全结果更完整,例如当输入--file之后,我们希望补全特殊的文件(假设以.sh结尾的文件)

case "${prev}" in
-f|--file)
COMPREPLY=( $(compgen -o filenames -W "`ls *.sh`" -- ${cur}) )
;;
esac

现在再执行foo命令,--file参数的值也可以补全了:

monster@monster-Z:~/TEST/sh$ foo --file
array.sh test1.sh
hello.sh test.sh
pipe.sh while.sh

在补全函数中加入如下命令:

_get_comp_words_by_ref -n : cur prev words cword

变量cur中包含了命令行当前所在的单词,prev为前一个单词, words为完整的命令行单词数组,cword为单词数组的当前下标

参考连接:

1、http://kodango.com/bash-competion-programming

2、https://debian-administration.org/article/317/An_introduction_to_bash_completion_part_2

最新文章

  1. UVA1585
  2. Win10 UWP 开发系列:支持异步的SQLite
  3. Spark代码调优(一)
  4. mongodb遇到的错误
  5. lucene历史版本地址
  6. 【JavaScript】JavaScript回调函数
  7. android 状态栏(StatusBar)
  8. 《Spring敲门砖之基础教程第一季》 第一章 概要介绍
  9. hdu1020Encoding
  10. ASP.NET MVC性能优化工具 MiniProfiler
  11. RethinkDB创始人教你如何打造一个伟大的互联网产品
  12. JQuery的插件开发——重点
  13. mac qq怎么删除全部聊天记录
  14. CentOS7:解决Packagekit占用yum问题
  15. 【Python】exe2shellcode,shellcode2exe
  16. .NET零基础入门06:面向对象入门
  17. soj2012.King(有向图+蛋疼得一逼)
  18. android 视频 2017
  19. kafka详解
  20. chrome一个奇怪的问题

热门文章

  1. bootstrapcss3触屏滑块轮播图
  2. canvas画布在主流浏览器中的尺寸限制
  3. 数据持久化(一)--NSKeyedArchiver
  4. java反射机制一个例子
  5. 深入理解Objective-C Runtime
  6. NSString 字符串替换
  7. unity3D 常用快捷键
  8. jQuery.noConflict() 函数
  9. EMC Documentum DQL整理(二)
  10. markdown学习笔记 (一)