zoukankan      html  css  js  c++  java
  • 命令行选项补全

    1、compgen

    compgen(筛选命令)

    这个命令,用来筛选生成 匹配单词的 候选补全结果。

    -W wordlist

    分割 wordlist 中的单词,生成候选补全列表

    [root@localhost ~]#compgen -W 'word1 word2 test'
    word1
    word2
    test
    [root@localhost ~]#compgen -W 'word1 word2 test' word
    word1
    word2
    [root@localhost ~]#
    要列出所有可用的命令,只需键入以下命令
    compgen -c
    要列出可用的所有bash shell别名,请输入:
    compgen -a
    显示所有bash内置插件,内建命令
    compgen -b
    显示所有bash关键字
    compgen -k
    显示所有bash函数
    compgen -A function
    
    compgen -W "aa ab bb cc" -- "a"
    表示从”aa ab bb cc”  匹配出以“a”开头的单词
    这条命令的返回结果就是 “aa ab”。

    2、complete

    complete补全命令

    -F function

    执行shell 函数,函数中生成COMPREPLY作为候选的补全结果

    -C command

    将 command 命令的执行结果作为候选的补全 结果

    -Gpattern

    将匹配 pattern的文件名作为候选的补全结果

    -W wordlist

    分割 wordlist 中的单词,作为候选的补全结果

    -p [name]

    列出当前所有的补全命令

    -r [name]

    删除某个补全命令

    complete -F  __cmd_HUB  bsu
    表示当执行bsu命令时,自动补全的候选单词由函数__cmd_HUB计算得到,具体的承载容器是变量COMPREPLY。
    特别说明一下,像这样的complete -F XXX   ./test.sh  也是合法的。
    如果XXX的计算后得到COMPREPLY=(aa bb cc), 则输入 ./test.sh 之后, 按tab键,可以自动弹出候选选项aa bb cc 自动补全是Bash自带的一个强大的功能,允许通过编码指定命令参数如何补全。
    通常,补全脚本会放在
    /etc/bash_completion.d/ 目录下,方便统一启用所有补全脚本。 这里例子的命令为 foo [root@localhost bash_completion.d]#cat foo.sh #!/bin/bash _foo() { local cur=${COMP_WORDS[COMP_CWORD]} COMPREPLY=( $(compgen -W "exec help test" -- $cur) ) } complete -F _foo foo 如下,测试foo命令是否自动补全 [root@localhost ]# chmod +x /etc/bash_completion.d/foo.bash [root@localhost ]# source /etc/bash_completion.d/foo.bash [root@localhost ]# foo [Tab][Tab] exec help test 以上,source是为了这个foo.bash在当前会话生效。默认情况下,这个补全脚本不会被执行到,也就是说,补全命令未激活。
    需要source激活这个脚本,就可以没有顾虑地使用了。 为了避免每次都要source一次,可以在bashrc加上这个命令。 bashrc全局配置在不同 linux 发行版可能位置不同,如下: Centos
    /etc/bashrc Ubuntu /etc/bash.bashrc (如果只在当前帐号生效,只要配置 ~/.bashrc 即可) 在bashrc文件末尾加上 source /etc/bash_completion.d/foo.bash,这样,每次登录到linux后,就会激活这个补全脚本。
    # complete -W 'word1 word2 word3 test' foo
    # foo w<Tab>
    # foo word<Tab>
    # complete -p
    complete -W 'word1 word2 word3 test' foo
    complete -o filenames -F __udisks udisks
    # complete -r foo
    # complete -p
    complete -o filenames -F __udisks udisks
    complete命令指定如何对各个名称进行补全。如果指定了选项“-p”或者没有指定任何选项,则把已有的补全方法用一种可以重新作为作为输入的格式打印出来。
    选项“-r”用以删除指定名称的补全方法,不指定名称时删除所有的名称的补全方法。
    选项“-D”的意思是其后的选项和动作将应用到默认命令补全,也就是说之前未定义的补全命令也可以补全。
    选项“-E”的意思是其后的选项和动作将应用到空命令补全,也就是说补全空白行。
    对于选项“-G”、“-W”、“-X”、“-P”和“-S”,应该使用括号进行保护,防止补全开始前被扩展。 “-o bashdefault”:如果没有生成补全条目,就使用bash默认的其它补全。 “-o default”:如果没有生成补全条目,就使用“readline”默认的文件名补全。 “-o dirnames”:如果没有生成补全条目,就进行目录名补全。 “-o filenames”:告诉“readline”生成文件名,以便进行与文件名相关的处理,
      例如在目录名后面加上斜杠,引用特殊字符,去掉行尾的空格,目的是用于shell函数。 “
    -o noquote”:告诉“readline”不引用文件名,默认会进行引用。 “-o nospace”:告诉“readline”在补全的名称后不添加空格,默认添加空格。 “-o plusdirs”:生成补全条目之后,还会进行目录名补全并把结果添加到其它动作得到的结果中。 “-A alias”:别名,同选项“-a”。 “-A arrayvar”:数组变量名。 “-A binding”:“readline”键绑定名。 “-A builtin”:shell内建命令名,同选项“-b”。 “-A command”:命令名,同选项“-c”。 “-A directory”:目录名,同选项“-d”。 “-A disabled”:不可用的shell内建命令名。 “-A enabled”:可用的shell内建命令名。 “-A export”:导出的shell变量名,同选项“-e”。 “-A file”:文件名,同选项“-f”。 “-A function”:shell函数名。 “-A group”:组名,同选项“-g”。 “-A helptopic”:内建命令help支持的帮助主题。 “-A hostname”:主机名,从shell环境变量HOSTFILE中获取。 “-A job”:作业名,同选项“-j”。 “-A keyword”:shell保留字,同选项“-k”。 “-A running”:正在运行的作业名。 “-A service”:服务名,同选项“-s”。 “-A setopt”:内建命令set的选项“-o”可用的参数。 “-A shopt”:内建命令shopt可接受的选项名。 “-A signal”:信号名。 “-A stopped”:暂停的作业名。 “-A user”:用户名,同选项“-u”。 “-A variable”:所有的shell变量名,同选项“-v”。 “-C command”:在子shell中执行命令,并把其结果作为补全条目。 “-F function”:在当前的shell环境中执行函数function,执行时,
      参数“$1”表示那个参数正在进行补全的命令名,参数“$2”表示补全的名称,
      参数“$3”表示补全的名称前面的单词,表示结束执行时,从数组变量COMPREPLY中获取补全条目。 “-G globpat”:使用文件名扩展模式globpat进行扩展以生成可能的补全条目。 “-P prefix”:在所有的选项应用到补全结果后,在结果前添加前缀prefix。 “-S suffix”:在所有的选项应用到补全结果后,在结果后添加后缀suffix。 “-W wordlist”:使用特殊变量IFS中的字符拆分单词列表wordlist,并扩展拆分后的每个单词,结果中与待补全单词 匹配的条目就是补全条目。 “-X filterpat”:filterpat是进行文件名扩展时使用的模式,它作用于通过前面的选项和参数生成的补全列表,
      并把每个与过滤模式匹配的条目删除,模式中前导的叹号表示否定,这时会删除与过滤模式不匹配的条目。

    3、compopt

    compopt(修改补全命令设置)
    这个命令可以修改补全命令设置,注意了,这个命令必须在补全函数中使用,否则会报错。
    # help compopt
    compopt: compopt [-o|+o option] [-DE] [name ...]
    重点说明:
    +o option    启用 option 配置
    -o option    弃用 option 配置
    
    例如,设置命令补全后不要多加空格,方法如下:
    compopt -o nospace

    4、内置补全变量

    除了上面三个命令外,Bash还有几个内置变量来辅助补全功能,如下:

    COMP_WORDS

    类型为数组,存放当前命令行中输入的所有单词

    COMP_CWORD

    类型为整数,当前输入的单词在COMP_WORDS中的索引

    COMPREPLY

    类型为数组,候选的补全结果

    COMP_WORDBREAKS

    类型为字符串,表示单词之间的分隔符

    COMP_LINE

    类型为字符串,表示当前的命令行输入字符

    COMP_POINT

    类型为整数,表示光标在当前命令行的哪个位置

     总结:

    1. 查看已有的命令行补全
    在启用可编程的命令行补全功能后,就已经有了一些定义好的命令补全功能。complete 命令用于定义命令行补全。
    要查看已有的命令行补全,如下使用 complete 命令:
    complete -p | less
    上面例子中的 -p 选项是可选的。
    

    2. 定义一个命令名补全 通过 -c 选项可以将所有的可用命令作为一个命令的补全参数。在下面的例子里面,为 which 命令定义了一个补全
    (LCTT译注:在按两下 TAB 时,可以列出所有命令名作为可补全的参数)。 $ complete
    -c which $ which [TAB][TAB] Display all 2116 possibilities? (y or n) 如上,如果按下 ‘y’,就会列出所有的命令名。

    3. 定义一个目录补全 通过选项 -d,可以定义一个仅包含目录名的补全参数。在下面的例子中,为 ls 命令定义了补全。 $ ls countfiles.sh dir1/ dir2/ dir3/ $ complete -d ls $ ls [TAB][TAB] dir1/ dir2/ dir3/ 如上,连按下 TAB 仅会显示目录名。

    4. 定义一个后台任务名补全 补全功能也能够以任务名作为补全参数。选项 -j 可以定义任务名作为传递给命令的参数,如下: $ jobs [1]- Stopped cat [2]+ Stopped sed 'p' $ complete -j ./list_job_attrib.sh $ ./list_job_attrib.sh [TAB][TAB] cat sed 关于后台任务,你可以参考 Linux 后台任务中的例子了解如何管理后台任务。

    5. 通过 IFS 变量分割字符串得到补全值 可以通过 -W 选项定义补全值列表,然后通过 IFS 环境变量进行切分。切分结果会展开变量并作为补全显示。 $ export IFS=" " $ complete -W "bubble quick" ./sort_numbers.sh $ ./sort_numbers.sh [TAB][TAB] bubble quick 如上所述,字符串通过 IFS 分隔符进行切分后,内嵌的变量会被展开为变量值,所以可以如下使用变量: $ echo $SORT_TYPE1 bubble $ echo $SORT_TYPE2 quick $ complete -W "$SORT_TYPE1 $SORT_TYPE2" ./sort_numbers.sh $ ./sort_numbers.sh [TAB][TAB] bubble quick

    6. 写个函数来生成补全 你可以引入一个函数来定义补全。使用 -F 选项将函数名传给 complete 命令,执行函数生成补全内容。例如,函数如下: _parser_options() { local curr_arg; curr_arg=${COMP_WORDS[COMP_CWORD]} COMPREPLY=( $(compgen -W '-i --incoming -o --outgoing -m --missed' -- $curr_arg ) ); } 在上述函数中: COMPREPLY : 该数组控制连按下 TAB 后显示的结果 COMP_WORDS : 该数组包含命令行输入的单词 COMP_CWORD : COMP_WORDS 数组的索引,使用它来区分命令行可以访问的单词位置 compgen : -W 基于 $current_arg 提供可能的补全及其参数 该函数放在 parser_option 文件中,并通过 source 命令引入: $ source parser_option 将该函数和你的 parser.pl 脚本关联起来: $ complete -F _parser_options ./parser.pl $ ./parser.pl [TAB][TAB] -i --incoming -o --outgoing -m --missed 如上,parser.pl 的选项是由函数 _parser_options() 生成的。 提示: 查看/etc/bash_completion 来了解更多的可编程补全函数。

    7. 当第一个规则没有生成结果时,就使用第二个 如果定义的补全规则没有生成匹配时,可以使用 -o 选项生成补全。 $ complete -F _count_files -o dirnames ./countfiles.sh 如上,为 ./countfiles.sh 定义了 _count_files 补全函数。 如果 the _count_files() 函数没有生成任何匹配的话,就会触发目录补全。 $ ls countfiles.sh dir1/ dir2/ dir3/ $./countfiles.sh [TAB][TAB] dir1 dir2 dir3

    8. #compgen最常用的选项是-W,通过-W参数指定空格分隔的单词列表。
    h即我们在命令行Command-line当前键入的单词,执行完后会输出候选的匹配列表,这里是以h开头的所有单词. $ compgen -W 'hi hello how world' h hi hello how

    9. # 指定通过_test函数对test进行补全 $ function _test() > { > echo -e " " > declare -p COMP_WORDS > declare -p COMP_CWORD > declare -p COMP_LINE > declare -p COMP_WORDBREAKS > } $ complete -F _test test 再输入以下命令按补全: [root@localhost simon]#test a b c [tab][tab] declare -a COMP_WORDS='([0]="test" [1]="a" [2]="b" [3]="c" [4]="")' declare -- COMP_CWORD="4" declare -- COMP_LINE="test a b c " declare -- COMP_WORDBREAKS=" "'><=;|&(:"

    例子:

    1、首先实现命令脚本

    #!/bin/bash
    function Usage()
    {
        echo -e "**********************************************************************"
        echo -e "Usage:"
        echo -e "Options:"
        echo -e "-h,-H,		Show help information."
        echo -e "**********************************************************************"
        echo
    }
    while getopts "hH?" arg
    do
        case $arg in
            h|H|?)
                Usage $Name
                exit 1
                ;;
        esac
    done
    #脚本必须运行在root权限下
    if [ `id -u` -ne 0 ]; then
        echo -e "This script must be run as root! 
    "
        exit 1
    fi
    case $1 in
    'foo')
        case $2 in
            'foo1'|'foo2'|'foo3')
              echo -e "This is $2! 
    "
              ;;
        *)
            Usage $Name
            exit 1
              ;;
        esac;;
    'test')
        case $2 in
        'test1'|'test2')
            echo -e "This is $2! 
    "
            ;;
        *)
            Usage $Name
            exit 1
              ;;
        esac;;
    *)
        Usage $Name
        exit 1
          ;;
    esac
    exit 0

    2、接着,实现命令补全脚本

    #!/bin/bash
    _parser_options()
    {
        COMPREPLY=()
        local cur=${COMP_WORDS[COMP_CWORD]};    #获取最后一个选项
        local cmd=${COMP_WORDS[COMP_CWORD-1]}; #获取最后第二个选项
        if [ ${COMP_CWORD} -eq 1 ];
        then
            COMPREPLY=( $(compgen -W 'foo test' -- $cur) );
        elif [ ${COMP_CWORD} -eq 2 ];
        then
            case $cmd in
            'foo')
                  COMPREPLY=( $(compgen -W 'foo1 foo2 foo3' -- $cur) ) 
                    compopt -o nospace #是将补全后自动加的空格删掉
                  ;;
    
            'test')
                  COMPREPLY=( $(compgen -W 'test1 test2' -- $cur) ) ;;
                  compopt -o nospace #是将补全后自动加的空格删掉
            *)
                  ;;
            esac
        fi
    
    }
    #complete -F _parser_options -o dirnames ramtest.sh
    complete -F _parser_options ramtest.sh

    3、测试

    [root@localhost simon]# cp parse.sh /etc/bash_completion.d/
    [root@localhost simon]# source /etc/bash_completion.d/parse.sh
    [root@localhost simon]# cp ramtest.sh /bin/
    [root@localhost simon]# ramtest.sh
    **********************************************************************
    Usage:
    Options:
    -h,-H,          Show help information.
    **********************************************************************
    
    [root@localhost simon]# ramtest.sh [tab][tab]
    foo   test
    [root@localhost simon]# ramtest.sh foo foo [tab][tab]
    foo1  foo2  foo3
    [root@localhost simon]# ramtest.sh foo foo
    foo1  foo2  foo3
    [root@localhost simon]# ramtest.sh foo foo1[tab][tab]
    foo1
    [root@localhost simon]# ramtest.sh foo foo1
  • 相关阅读:
    Linux磁盘空间释放问题
    Linux终端复用神器-Tmux使用梳理
    Linux下路由配置梳理
    Gitlab利用Webhook实现Push代码后的jenkins自动构建
    Tomcat 内存溢出 "OutOfMemoryError" 问题总结 (JVM参数说明)
    Centos下SVN环境部署记录
    Docker格式化输出命令:"docker inspect --format" 学习笔记
    ngx_pagespeed-nginx前端优化模块介绍
    git pull 总要求输入账号和密码解决?
    Android Studio之BuildConfig类
  • 原文地址:https://www.cnblogs.com/ggzhangxiaochao/p/13162979.html
Copyright © 2011-2022 走看看