• Ukieweb

    佳的博客

    曾梦想仗剑天涯,后来工作忙没去。

自定义设置 linux tab 自动补全 compgen complete

在Linux命令行下,输入字符后,按两次Tab键,shell 就会列出以这些字符打头所有可用命令。如果只有一个命令匹配到,按一次 Tab 键就自动将这个命令补全。默认情况下,会自动列出当前目录的文件作为自动补全。

自动补全是Bash自带的一个强大的功能,允许通过编码指定命令参数如何补全。通常,补全脚本会放在 /etc/bash_completion.d/ 目录下,方便统一启用所有补全脚本。

它涉及到的命令有:

  • 自动补全名 complete

  • 筛选命令 compgen

一,小 demo

在  /usr/share/bash-completion/completions 或者 /etc/bash_completion.d/下 新建文件 laojia 

内容为:

_laojia_completion_()
{
  local curr_arg=${COMP_WORDS[COMP_CWORD]}  #当前输入的字符串
  COMPREPLY=( $(compgen -W "xx jj bb cc" -- $curr_arg ) );
}
complete -F _laojia_completion_ laojia lj  # 会对 laojia 和 lj 进行补全 即使这个命令根本不存在

新建一个可执行命令 laojia (这步其实可以省略)

 cd /usr/local/bin/
 touch  laojia
 chmod +x laojia

尝试补全

[root@localhost bin]# exec bash
[root@localhost bin]# laojia 
bb  cc  jj  xx  
[root@localhost bin]# laojia

二、补全命令 complete 

[root@localhost bash_completion.d]# help complete
complete: complete [-abcdefgjksuv] [-pr] [-DE] [-o option] [-A action] [-G globpat] [-W wordlist]  [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [name ...]
    Specify how arguments are to be completed by Readline.
    
    For each NAME, specify how arguments are to be completed.  If no options
    are supplied, existing completion specifications are printed in a way that
    allows them to be reused as input.
    
    Options:
      -p        print existing completion specifications in a reusable format
      -r        remove a completion specification for each NAME, or, if no
        NAMEs are supplied, all completion specifications
      -D        apply the completions and actions as the default for commands
        without any specific completion defined
      -E        apply the completions and actions to "empty" commands --
        completion attempted on a blank line
    
    When completion is attempted, the actions are applied in the order the
    uppercase-letter options are listed above.  The -D option takes
    precedence over -E.
    
    Exit Status:
    Returns success unless an invalid option is supplied or an error occurs.
  • -W wordlist: 自动补全使用的 wordlist, 使用 IFS 分割,会和当前用户输入的Word前缀比较,提示那些匹配的 word list.

  • -S suffix: 向每个自动补全 word 后添加 suffix 后缀.

  • -P prefix: 向每个自动补全 word 后添加 prefix 前缀.

  • -X filterpat: 对于文件名,将匹配 pattern 的文件名从 completion list 中移除(exclude), pattern中使用 表示否定

  • -G globpat: 对于文件名,将匹配 pattern 的文件名作为可能的 completion. 与 -X 刚好相反,-X “!*.foo” -G “*.foo”作用相同

  • -C command: 将 command 命令执行结果作为可能的 completion.

  • -F function: 执行 shell function,在 function 对 COMPREPLY 这个数组复制,作为可能的 completion

  • -p [name]: 打印当前自定义的 complete

  • -r [name]:  删除当前自定义的 complete

  • -A action : 表示生成可能的 completion 的方式,包括 alias, file, directory 等,具体请参看文后的参看资料

使用 -C -G -X 参数样例

# ls的自动补全为当前目录
complete -C "pwd"  ls  

# ls的自动补全为.py文件
complete -G "*.py" ls 

# ls的自动补全为非.py文件
complete -X "*.py" ls

使用 -F 参数自定义补全函数

function _mycomplete_()
{
    local cmd="${1##*/}"  # 当前命令
    local word=${COMP_WORDS[COMP_CWORD]}  #当前输入的字符串
    local line=${COMP_LINE}  #整行字符串
    local xpat='*.py'  # pattern
    # 根据word的值来补全当前非.py的文件file.
    COMPREPLY=($(compgen -f -X "$xpat" -- "${word}"))
}

# _mycomplete_函数可定义在.bash_profile中,然后执行
source ~/.bash_profile

# 当然也可多个命令共用一个function, 只要_myfunction_作区分即可,比如对cmd执行case语句
# 生成不同的xpat
 
complete -F _mycomplete_ myfoo  #使用 _mycomplete 作为 myfoo 的自动补全

三、筛选命令 compgen

[root@localhost bash_completion.d]# help compgen
compgen: compgen [-abcdefgjksuv] [-o option]  [-A action] [-G globpat] [-W wordlist]  [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [word]
    Display possible completions depending on the options.
    
    Intended to be used from within a shell function generating possible
    completions.  If the optional WORD argument is supplied, matches against
    WORD are generated.
    
    Exit Status:
    Returns success unless an invalid option is supplied or an error occurs.
[root@localhost bash_completion.d]#

参数虽然多,但是用的最多的只有 -W 参数啦

命令:compgen -W "aa ab bb cc" -- “a”   
表示从"aa ab bb cc"  匹配出以“a”开头的单词

这条命令的返回结果就是 “aa ab”。

四、compopt(修改补全命令设置)了解即可

这个命令可以修改补全命令设置,注意了,这个命令必须在补全函数中使用,否则会报错。

# help compopt
compopt: compopt [-o|+o option] [-DE] [name ...]
  • +o option:启用 option 配置

  • -o option:弃用 option 配置

例如,设置命令补全后不要多加空格,方法如下:

compopt -o nospace

五、例子讲解

# cat /etc/bash_completion.d/foo.bash 
_foo()
{
    COMPREPLY=()
    local cur=${COMP_WORDS[COMP_CWORD]};
    local cmd=${COMP_WORDS[COMP_CWORD-1]};
    case $cmd in
    'foo')  # foo有3个参数,分别是 help, read, test
          COMPREPLY=( $(compgen -W 'help test read' -- $cur) ) ;; 
    'test')  # test 从文件中提取2级参数
          local pro=( $(awk '{print $1}' /data/a.txt) )
          COMPREPLY=( $(compgen -W '${pro[@]}' -- $cur) ) ;;
    '*')
          ;;
    esac
    if [[ "${COMP_WORDS[1]}" == "read" && ${COMP_CWORD} -eq 2 ]]; then
          local pro=($(pwd))
          cd /data
          compopt -o nospace
          COMPREPLY=($(compgen -d -f -- $cur))
          cd $pro
    fi
    return 0
}
complete -F _foo foo

例子中, foo有3个参数,分别是 help, read, test

  • read 测试遍历 /data 目录下所有文件

  • test 测试从文件中提取2级参数

  • help 只是演示,没有特殊作用

0
0
下一篇:shell 截取字符串 %, %%,:

0 条评论

老佳啊

85后,大专学历,中原人士,家里没矿。

由于年轻时长的比较帅气,导致在别人眼里,我一直不谈恋爱的原因是清高,实则是自己的小自卑。最大的人生目标就是找一个相知相爱相容的人,共度余生。

和人相处时如果能感受到真诚,会非常注重彼此的关系,对别人没有什么心机,即使有利益冲突,一般也会以和为贵,因为在这个世界上,物质的东西,从来不会吸引到我。

特别迷恋那些大山大水,如果现在还能隐居,可能早就去了。对那些宏伟的有底蕴的人文景观比较不感冒。

从事于IT行业,却一直对厨房念念不忘,由于身材魁梧,总觉得自己上辈子是个将军,可惜这辈子没当兵,也不会打架。