10种有用的Linux bash自动补全实例

发布 : 2017-06-14 分类 : translations 浏览 : --

原文链接

在Linux的终端中,如果敲两次TAB键,就会列出所有可用的命令(如果已经输入了部分字符,就会显示以这些字符为开头的命令)。

其实这并不新鲜,也许你早就知道了。这个功能被叫做bash自动补全。基础的文件名和目录名自动补全在bash中默认是支持的。

但是,我们可以升级bash补全,让它进入更高一级的命令补全。

这篇教程解释了应该怎样通过调用参数自动补全和命令参数的自动补全。

比如,在敲入write命令后,如果敲两次tab, 自动补全会提供进行write操作的用户的列表

1
2
3
4
5
6
$ write [TAB][TAB]
bala raj
jason randy
john ritu
mayla thomas
nisha www-data

在下面这个例子中,它会为telnet命令显示有效的主机名:

1
2
$ telnet [TAB][TAB]
localhost dev-db fileserver

要在终端中得到可编程的自动补全功能,只需要像下面这样运行 /etc/bash_completion 就好了(小数点可以用source代替)

1
$ . /etc/bash_completion

你也可以在 /etc/bash.bashrc (ubuntu linux 13.04) 中取消以下几行的注释,这样你就不用显式的运行上面的命令了:

1
2
3
4
5
6
7
if ! shopt -oq posix; then
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi

如果你没有在 /etc/bash_completion 找到上面几行的话,就需要手动安装bash_completion


1.查看已有的bash补全

在开启了bash补全功能之后,会有一套已经定义好的bash补全。complete命令是用来定义bash补全的,要查看已有的补全,可以用下面这条命令:

1
$ complete -p | less

-p 参数是上面的例子中是可选的,管道操作输出给less是因为输出的结果可能超过一屏,为了方便查看,顾使用less

2.bash提供的标准补全

bash 默认为Linux用户提供了以下标准补全:

  1. 变量名补全(Variablename)
  2. 用户名补全(Username)
  3. 主机名补全(Hostname)
  4. 路径名补全(Pathname)
  5. 文件名补全(Pathname)

以上补全在另一篇文章有相关讨论

3.命令(Commands)自动补全

-c 参数来定义获取命令的补全。在下面的例子中,我们为which命令定义了补全:

1
2
3
4
$ complete -c which

$ which [TAB][TAB]
Display all 2116 possibilities? (y or n)

输入y,就会得到所有命令的列表

4.目录(Directories)自动补全

-d 参数来定义只获取目录的补全。在下面的例子中,我们为ls定义了这个补全:

1
2
3
4
5
6
7
$ ls
countfiles.sh dir1/ dir2/ dir3/

$ complete -d ls

$ ls [TAB][TAB]
dir1/ dir2/ dir3/

作为对比,可见在定义了新的补全规则后,敲tab就只会出现目录了。

5.后台任务(Jobs)自动补全

通过补全,同样可以让一个命令获取后台运行的命令的名字作为参数,像下面这样使用 -j 参数就可以了:

1
2
3
4
5
6
7
8
$ jobs
[1]- Stopped cat
[2]+ Stopped sed 'p'

$ complete -j ./list_job_attrib.sh

$ ./list_job_attrib.sh [TAB][TAB]
cat sed

说到后台任务,你也应该知道如何管理Linux的后台任务

6.前缀、后缀自动补全

自动补全可以在真正的补全的前面添加想要的前缀,后面添加后缀。在下面的例子中,前缀和后缀的补全规则被用于 list_job_attrib.sh

1
2
3
4
5
6
7
8
$ jobs 
[1]+ Stopped cat

$ complete -P '">' -S '<"' ./list_job_attrib.sh

$ ./list_job_attrib.sh [TAB][TAB]

$ ./list_job_attrib.sh ">cat<"

7.文件名和目录名的排除补全

假设某个脚本运行结束后,输出结果像下面这样被输出到了 output 目录中

1
2
3
4
$ cd output/

$ ls
all_calls.txt incoming_calls.txt outgoing_calls.txt missed_calls.txt parser_mod.tmp extract.o

在上面的结果中,如果你想在执行ls的时候,自动补全忽略 .tmp.o 文件,可以这样做:

1
2
3
4
5
6
7
8
$ export FIGNORE='.tmp:.o'

$ complete -f -d ls

$ cd output

$ ls [TAB][TAB]
all_calls.txt incoming_calls.txt outgoing_calls.txt missed_calls.txt

FIGNORE是shell变量,它用来在自动补全结果中排除文件名中包含后缀的文件。

8.用IFS分割字符串来获取补全值

单词列表可以用-W参数加上IFS值进行分割,然后每一个分割后的单词都会在补全结果中出现:

1
2
3
4
5
6
$ export IFS=" "

$ complete -W "bubble quick" ./sort_numbers.sh

$ ./sort_numbers.sh [TAB][TAB]
bubble quick

如上所示,句子通过分隔符进行分割,被展开为单词,所以它也可以像下面这样使用:

1
2
3
4
5
6
7
8
9
$ echo $SORT_TYPE1
bubble

$ echo $SORT_TYPE2
quick

$ complete -W "$SORT_TYPE1 $SORT_TYPE2" ./sort_numbers.sh
$ ./sort_numbers.sh [TAB][TAB]
bubble quick

9.使用自己的函数来生成补全

complete命令允许你使用一个函数来定义补全规则,使用-F参数,传递函数名给complete命令,函数被执行来生成补全规则。例如,函数可以写成下面这个样子:

1
2
3
4
5
6
7
8
_parser_options()
{
local curr_arg;

curr_arg=${COMP_WORDS[COMP_CWORD]}

COMPREPLY=( $(compgen -W '-i --incoming -o --outgoing -m --missed' -- $curr_arg ) );
}

在这个函数中,

  1. COMPREPLY: 保存补全结果的数组
  2. COMP_WORDS: 输入到命令行中的单词数组
  3. COMP_CWORD:COMP_WORDS中的索引,用这个索引,可以获取已经输入的命令行中不同位置的单词
  4. compgen: -W参数获取可能的补全值,然后不同的参数在$current_arg的基础上被选择

这个函数保存在 parser_option 中,被像下面这样被引用

1
source parser_option

将这个函数像下面这样绑定到你的脚本上:

1
2
3
4
$ complete -F _parser_options ./parser.pl

$ ./parser.pl [TAB][TAB]
-i --incoming -o --outgoing -m --missed

如上所示,补全规则通过_parser_options函数来生成。

提示:查看 /etc/bash_completion 可以获取更多函数来完成你的自定义补全规则

10.当主规则没有生成时的二级规则

如果主要补全规则没有任何补全匹配结果的时候,那么与之伴随的另一个参数-o的选择将会用于匹配补全规则。

1
$ complete -F _count_files -o dirnames ./countfiles.sh

在上面的例子中,_count_files 被用来生成 ./countfiles.sh 的自动补全规则,如果 _count_files 没有生成任何补全匹配的话,目录名将被作为匹配规则。

1
2
3
4
5
$ ls 
countfiles.sh dir1/ dir2/ dir3/

$./countfiles.sh [TAB][TAB]
dir1 dir2 dir3
本文作者 : hellflame
原文链接 : https://hellflame.github.io/2017/06/14/linux-bash-auto-complete/
版权声明 : 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
留下足迹
点击通过issue留言