很多命令都会提供一个bash-complete的脚本,在执行该命令时,敲tab可以自动补全参数,会极大提高生产效率。docker亦如此,如:yum install docker后,会有一个文件: /usr/share/bash-completion/completions/docker ; 显然,该脚本是用于bash自动补全的,但是,不幸的是,直接 source 执行该脚本后,docker命令后敲tab,有如下错误:
难道docker的bash自动补全还能有问题?
放狗一搜,解决办法如下:
我这里虽然安装了bash-completion ,但是没有执行其中的一个文件:
1 |
/usr/share/bash-completion/bash_completion |
该文件中有上面缺少的命令,自然,执行该文件就解决了。
其实 bash_completion 包中已经包含了一堆常用命令的bash自动补全的脚本的:
bash补全脚本编写:(实例)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
#!/bin/bash #该脚本执行后,输入alissh 空格后敲tab键就可以提示阿里ecs的名字 #ips 命令可以输出阿里ecs的: 名字 ip 说明 #alissh complete complete -F alissh_complete alissh function alissh_complete() { cur="${COMP_WORDS[COMP_CWORD]}" opts=$(ips|awk '{print $1}') COMPREPLY=($(compgen -W "$opts" -- {cur})) } function alissh() { name=$1 ip=$(ips|grep "$1" |awk '{print $2}') ssh $ip } |
complete -F func cmd 其中func的规则:
func可以接受到3个参数:
$0: 就是bash
$1: 命令名
$2: 需要补全的单词的一部分
$3: 上一个完整的单词 , 如果当前要补全的是第一个参数,则上一个完整的单词就是命令名
使用命令(任何语言)来实现命令补全(不过还是shell方便,实在不会shell就选择其他语言):
通过命令 mycomplete 给命令phpor来补全:
1 |
complete -C mycomplete phpor |
其中: mycomplete 命令将接到三个参数:
$1: 命令名(就是phpor)
$2: 需要补全的单词
$3: 命令行中出现的最后一个完整的单词
mycomplete要做的事情就是根据最后一个完整的单词来推测下个(要补全的)单词;只是如果命令行中已经包含了超过3个单词,则第二个单词信息将得不到; 其实不是的,只是从命令行参数中得不到,从环境变量是可以得到的,环境变量 COMP_LINE 保存了整个命令行的内容,命令行参数只是有助于我们定位光标的位置。
complete -C 和 -F 的说明
-C 指定一个命令; -F 指定一个函数 。 那么, -C 指定一个函数能行吗? -F 指定函数一定能行吗?
其实:
- -C 也能指定一个函数, 这两个选项的本质不是函数或者二进制程序的命令; 而是传递信息的方式不同(未验证,有时间再验证)
- 如果指定-C ,那么会通过参数和export出来的环境变量来传递
- 如果指定-F, 那么会通过参数和特定的全局变量来传递
可以通过是strace -e file bash 来了解bash自动补全的逻辑,可以通过函数命令complete来设置自动补全函数,如果不存在自动补全函数的话,会自动在补全目录下搜索当前执行的命令为名称的文件,如 ~/.local/share/bash-completion/completions/byssh ,我们可以在这里添加自动补全逻辑
complete 的更多用法参考: man bash 搜索: Programmable Completion
如果我们需要补全一些常规得到东西,可以使用 -A ,如:
- 补全当前shell中的函数: complete -A function xxx
- 补全当前shell中的alias : complete -A alias xxx
参考资料: