内置补全命令

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

Bash的自动补全的更多相关文章

  1. bash实现自动补全

    yum install -y bash-completion source /usr/share/bash-completion/bash_completion 执行后yum拥有选项自动补全功能 对于 ...

  2. RedHat/Fedora/Centos 下bash 自动补全命令

    本文转自:运维生存时间:http://www.ttlsa.com/linux/rhel- ... matically-function/ linuser  :http://www.linuser.co ...

  3. ipython, 一个 python 的交互式 shell,比默认的python shell 好用得多,支持变量自动补全,自动缩进,支持 bash shell 命令,内置了许多很有用的功能和函数

    一个 python 的交互式 shell,比默认的python shell 好用得多,支持变量自动补全,自动缩进,支持 bash shell 命令,内置了许多很有用的功能和函数. 若用的是fish s ...

  4. shell自动补全功能:bash和zsh

    首要一点:shell有多种,比如bash.zsh.csh.ksh.sh.tcsh等 因此,制作自动补全功能时,要先搞清楚,你使用的是哪种shell,各个shell制作方法是不同的,网上大部分介绍的是关 ...

  5. Visual Studio Code使用typings拓展自动补全功能

    转自:http://blog.csdn.net/liyijun4114/article/details/51658087 参考来源: 官方介绍: https://code.visualstudio.c ...

  6. mac git 的安装 及实现自动补全

    1.检查是否装了brew $ brew list如果没有,拷贝以下命令到终端 回车.可以安装好brewruby -e "$(curl -fsSL https://raw.githubuser ...

  7. 使用Linux自定义自动补全命令完善自己的shell脚本

    对于Linuxer来说,自动补全是再熟悉不过的一个功能了.当你在命令行敲下部分的命令时,肯定会本能地按下Tab键补全完整的命令,当然除了命令补全之外,还有文件名补全. Bash-completion ...

  8. [Git]08 如何自动补全命令

     [Git]08如何自动补全命令 如果你用的是 Bash shell,可以试试看 Git 提供的自动完成脚本.下载 Git 的源代码,进入 contrib/completion 目录,会看到一个g ...

  9. Mac系统实现git命令自动补全

    当我第一次使用mac电脑的时候,由于我是从事软件开发的程序员,所以必须经常要使用到git,然而发现在mac系统下,git不能实现命令的自动补全,然后网上查找资料,找到了解决办法,终于可以实现了git命 ...

随机推荐

  1. Oracle EBS Form Builder使用Java beans创建窗体

    最近有个项目,需要研究一下Oracle的E-Business Sutie(EBS),对于以前没接触此套件的我来说,简直太痛苦了.在网上找了一堆资料,试着进行Form二次开发,也遇到各类奇葩问题.目前遇 ...

  2. 分享最新15个加速 Web 开发的框架和工具

    我们为开发人员挑选了15个最新的  Web 开发框架,你肯定尝试一下这些新鲜的框架,有的可能略微复杂,有的提供了很多的配置选项,也有一些窗口小部件和界面交互的选择.他们将帮助你创建更优秀的网站,提供给 ...

  3. yii cookie ,session 操作

    一,在Yii中使用session 1,CHttpSession 与原生态php5的session使用差别是,php5使用session_start();$_session['key'] = $valu ...

  4. Android 用Fragment创建一个选项卡

    本文结合之前的动态创建fragment来进行一个实践,来实现用Fragment创建一个选项卡 本文地址:http://www.cnblogs.com/wuyudong/p/5898075.html,转 ...

  5. HTTPS时代全面到来,你准备好了吗?

    近一年可能有很多朋友发现在使用百度搜索时,是这个样子的 如我们所见,浏览器地址栏里的HTTP可能将成为永远的过去时,取而代之的是更安全的HTTPS. 首先,HTTPS是什么? HTTPS是Http O ...

  6. iOS学习19之OC类的扩展

    为一个类扩展功能:1.子类化:2.修改源代码:3.定义协议:4.Category:类目 1.Category 1> Category的作用 Category:也叫分类,类目,是为没有源代码的类扩 ...

  7. Swift中的部分更新与旧版的区别

    1. 函数中的外部变量名取消 “#”方式,仅能用直接命名方式 错误 func swift(#str :NSString){} 正确 func swift(str str :NSString){} 2. ...

  8. IDEA中,将文件夹加入classpath

    加载文件时遇到某些文件加载不到,可能是因为该文件不在classpath中. 加入方法: 1.File - Project Structure 2.如图 modules - 选择需要加入的文件夹, 点击 ...

  9. CEF3可行性

    Chromium Embedded Framework 顾名思义,内嵌式CHROME,详细的介绍参阅 http://yogurtcat.com/posts/cef/hello-cef.html 为什么 ...

  10. [转]android笔记--Intent和IntentFilter详解

    Intent用于启动Activity, Service, 以及BroadcastReceiver三种组件, 同时还是组件之间通信的重要媒介. 使用Intent启动组件的优势1, Intent为组件的启 ...