如何编写bash自动补全脚本

什么是bash的自动补全

Bash自动补全是为了帮助用户能够更快、更容易输入命令的一项功能。它能够在用户输入命令时敲击tab键后,提供可能的选项。

$ git<tab><tab> git git-receive-pack git-upload-archive gitk git-shell git-upload-pack $ git-s<tab> $ git-shell 工作原理

Bash补全脚本是一段使用bash内置命令command的代码,用于定义哪些补全建议可以对特定的可执行程序显示。这些补全建议既可以是简单的静态内容,也可以是高度复杂的。

为什么要使用 

自动补全功能能够为用户提供以下便利:

当可以自动完成时,帮助用户减少文本输入;

让用户知道输入的命令后续可以有哪些可选的参数;

避免输入错误,同时通过用户已经输入的内容隐藏或者展示可选项以提高用户体验。

开始上手

下面我们将开始一个演示。

首选,我们将会创建一个名为dothis的模拟可执行脚本。该脚本接受一个参数,表示用户执行历史中的序号,并执行序号对应的历史命令。例如,以下命令将会执行用户历史命令中序号为235的命令(我电脑上对应的是ls -a命令):

 

dothis 235

然后,我们将创建一个bash自动补全脚本,用以展示用户历史命令信息,并和dothis命令“绑定”起来。

$ dothis <tab><tab> 215 ls 216 ls -la 217 cd ~ 218 man history 219 git status 220 history | cut -c 8-

如何编写bash自动补全脚本

读者可以在位于GitHub上的本教程代码仓库中看见gif演示动图。

现在让我们开始吧。

创建可执行脚本

在工作目录中创建名为dothis的文件,并添加以下代码:

if [ -z "$1" ]; then echo "No command number passed" exit 2 fi exists=$(fc -l -1000 | grep ^$1 -- 2>/dev/null) if [ -n "$exists" ]; then fc -s -- "$1" else echo "Command with number $1 was not found in recent history" exit 2 fi

注意:

脚本首先检查调用时是否跟随这一个参数。

检查输入的数字是否在最近1000个命令中:

如果存在则使用fc命令执行对应的命令;

如果不存在则显示错误信息。

使用以下命令给脚本添加可执行权限:

chmod +x ./dothis

由于在后面的教程中将多次执行这个脚本,因此我建议将其放到系统PATH环境变量所指定的目录中,这样我们就能够直接输入dothis来执行它。

我将这个脚本安装到了我的$HOME/bin目录中:

install ./dothis ~/bin/dothis

如果您的系统中~/bin目录也在PATH环境变量中,也可以用这种方式安装。

现在让我们来验证脚本:

dothis

我们应该可以看见这样的输出:

$ dothis No command number passed

搞定。

创建自动补全脚本

创建一个名为dothis-completion.bash的文件,为了方便描述,从现在开始称该文件为自动补全脚本。

一旦在该文件中添加了一些代码,我们都需要source它以生效。注意,后面每次修改文件之后,都需要source这个文件。

后续我们将讨论如何让这个自动补全脚本在bash每次打开时自动生效。

静态补全

假设dothis应用支持一系列子命令,例如:

now

tomorrow

never

我们可以使用bash内置的complete命令来注册这个补全列表。用专业术语来说,我们通过complete命令为我们的应用定义了一个补全规范(completion specification,compspec)。

将以下内容添加到自动补全脚本中:

#/usr/bin/env bash complete -W "now tomorrow never" dothis

上述内容使用complete命令定义了:

通过-W参数提供了补全词列表;

指定该补全词列表适用的应用程序(这里作为dothis命令参数)。

前面提到过,每次编辑补全脚本后,都需要source该文件:

source ./dothis-completion.bash

现在让我们尝试在命令行中敲击两次tab键:

$ dothis <tab><tab> never now tomorrow

再来试下输入字母n之后的效果:

$ dothis n<tab><tab> never now

神奇!补全列表自动过滤出了只以字母n开头的选项。

注意:补全参数列表显示的顺序和我们在补全脚本中定义的顺序不同,它们已经经过自动排序。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/7abde8daf5e5ef373eea3856d785025d.html