Linux Shell 命令自动补全(各方资料汇总补全版)

在下所在的公司定义了一种路径,配合自定义的 loader 命令;遂命令在下完成自定义路径的自动补全需求。

关于Linux Shell命令自动补全已有的一些优秀 blog

  • 没有开花的树的《详解Linux Shell命令自动补全》
    • 这篇文章讲得比较系统,最后给的 demo 也特别优秀。
  • Linux中10个关于命令行自动补全的技巧
    • 注意这篇文章中的第10条:如果定义的补全规则没有生成匹配时,可以使用 -o 选项生成补全。强烈建议使用 -o default ,这样在没有补全项的情况下可以走系统默认的。
  • 【Bash百宝箱】shell命令行自动补全(compgen、complete、compopt)
    • 这篇文章的参数详解非常值得参考。

本人遇到的一些需求及解决方案:

需求一:从多个路径下获取补全候选项,并做去重
  • 解决方案写一个循环获取所有候选项,并且去重。这里记录一下 shell数组去重 ,和数组的使用。
array=()
array[0]="hello"
array[1]="hello"
# 数组去重(从一个贴吧里找到的,非原创)
array=($(awk -vRS=' ' '!a[$1]++' <<< ${array[@]}))

# 数组的使用(同样非原创,找不到链接了)
COMPREPLY=($(compgen -W "${array[*]}" -- "he"))
需求二:自定义路径 转化成 系统路径
  • 比如:我需要把 test:hello.world 转成 /.../hello/world
  • 这里需要注意的:COMP_WORDS 切割方式是按 COMP_WORDBREAKS 进行切割的。所以 test:hello.world 会被当成三个单词 test:hello.world;所以 COMP_CWORD 会增加得比较快。(都是坑=_=)
[root@localhost ~]# echo $COMP_WORDBREAKS
"'@><=;|&(:
  • 所以就有人有这样的需求:删除或者添加 COMP_WORDBREAKS,比如,我希望 . 当成分隔符,或者我希望 : 不是分割符。注意:千万别去改COMP_WORDBREAKS。这里首推 StackOverflow 的帖子,好久远的帖子了。
    • 对于删除分隔符,使用 _get_comp_words_by_ref -n : xxxxx 就可以把因 : 分割的单词拼起来。大家可以百度一下 _get_comp_words_by_ref 这个关键字,印象中有人详解过。
    • 对于添加分隔符,我参考了LinuxQuestions的帖子。思路是,自己把 . 作为分隔符切分,然后作为前缀在单词补全后补上,同时对于其他特殊字符,也可以作为后缀补上。
local pro=($(pwd))
local prefix=${cur%%.*}
cd $dict_path"/"$prefix
compopt -o nospace
COMPREPLY=( $(compgen -S "#" -P $prefix"." -d -f -- ${cur#*"."}) )
cd $pro
  • 将 cur 从右边数最后一个 . 的左边的内容作为前缀,利用 compgen-P 参数,这是增加前缀的参数。如果不加前缀,就会出现 test.f ,你希望 f 补全为 father,整体变成 test.father,这是你希望得到的。请注意,补全是整个单词补全,所以没有前缀的情况下,test.是会被删掉的,你只能得到 father ,所以 test. 必须首先抽出来当做前缀,然后补全得到 father 后拼到前面得到 test.father。(在下语文水平不好,希望描述清楚了这个巨坑)。同理,补全是补全单词,不会带像 cd 命令一样的 /,所以如果想自动补全 /,使用 -S 参数,增加后缀(代码中我增加了 # 后缀)。
  • compopt -o nospace 是将补全后自动加的空格删掉。
补充:/etc/bash_completion.d 目录下的补全脚本不生效
  • 有可能遇到将脚本放到 /etc/bash_completion.d 目录下不生效的情况,原因可能是:缺少/etc/profile.d/bash_completion.sh(根据为什么/etc/bash_completion.d 下面的bash自动补全脚本不生效)

结束语

折腾了两天,全程 tab 起飞,放飞自我。当然其中还学习了一些 shell 命令的基本写法,假装自己是运维。路漫漫其修远兮,加油加油!

你可能感兴趣的:(假装自己是运维)