代码之家  ›  专栏  ›  技术社区  ›  luca

Bash Completion:我们能用它做什么,未来会发生什么[关闭]

  •  3
  • luca  · 技术社区  · 15 年前

    Bash允许您使用TAB键完成参数中的命令名和文件名。 但是为什么不同时使用命令的常见选项呢?为什么不,甚至更好,一个完成系统,告诉你什么是一个选择,太?

    我听说了可编程完成。。但不知道它适合哪里。。

    所以我的问题是:有没有办法达到我的要求?与Bash结合的其他工具可能。。或者别的什么?

    7 回复  |  直到 15 年前
        1
  •  5
  •   Steven Schlansker    15 年前

    如果你想完成更棒的任务,那就看看 zsh . 它与bash非常相似,并采用了ksh、tcsh等的一些优秀特性,还修复了一些恼人的bash bug。

    它可以做一些非常酷的事情,包括完成scp的远程文件名(如果您设置了基于密钥的身份验证)和标签complete时的迷你文档 例如,前几天我在“jar”上的标签让我惊喜不已:

    [steven@sexy:~]% jar <tab>
    0  -- store only without using ZIP compression
    M  -- do not create manifest file
    etc...
    
        2
  •  2
  •   tangens    15 年前
        3
  •  2
  •   Ned Deily    15 年前

    在OS X上,您可以轻松地安装一组预定义的 bash 按照说明使用MacPorts完成 here . 查看中的示例 /opt/local/etc/bash_completion.d 可能会给你一些想法,使更多的。

        4
  •  1
  •   Ned Batchelder    15 年前

    这是bash的一个标准特性: programmable completion .

        5
  •  1
  •   vrutberg    15 年前
        6
  •  1
  •   Alan Haggai Alavi    15 年前

    Bash completion是非常可定制的,可以显示常用命令的选项。配置文件只需要指定。在Debian中,bash completion附带一组配置文件,这些文件完成不同命令的选项。

    例如:

    alanhaggai@neon:~$ tar
    A  c  d  r  t  u  x
    
        7
  •  0
  •   Matthew    11 年前

    我不喜欢这里的任何答案,我想提供几个具体的例子。

    我有时有一些目录有一个共同的前缀,希望能够cd到他们完成,只要键入唯一的部分目录名,这将是在中间或结束的目录名。

    我可以编写一个完成函数来完成这个任务:

    _cd(){
        # Backup old nullglob setting
        local shoptbakup="`shopt -p nullglob`"
        shopt -s nullglob
    
        local cur opts i opt
        local IFS=$'\n'
        cur="${COMP_WORDS[COMP_CWORD]}"
    
        # Home directory substitution
        if [[ "${cur:0:1}" == '~' ]]; then
            cur="$HOME/${cur:1}"
        fi
    
        if [[ $cur == */* ]]; then
            opts=(${cur}*/)
        else
            opts=(*${cur}*/)
        fi
    
        # Prevent trailing//
        i=0
        for opt in "${opts[@]}"; do
            #opts[$i]=${opt%${opt##*[!/]}}
            opts[$i]=${opt%/}
            i=$((i+1))
        done
    
        # Restore nullglob setting
        eval "$shoptbakup" 2>/dev/null
    
        COMPREPLY=("${opts[@]}")
    }
    complete -o filenames -o bashdefault -o nospace -F _cd cd
    

    所以现在在我的提示下,我可以这样做:

    $ ls
    test 6/  test 7/  test 8/  test1/  test2/  test3/  test4/  test5/
    $ cd 7[TAB]
    

    它会自动完成:

    $ cd test\ 7/
    

    您可能希望使用可编程完成的另一个原因是,如果您编写脚本并希望能够为您列出或完成选项。这一页有一些很好的例子:

    http://fahdshariff.blogspot.com/2011/04/writing-your-own-bash-completion.html

    下面是一个例子:

    假设我有一个叫做listanimals的脚本。我可以写一个完成函数来帮助填写选项

    # complete sendevent
    _listanimals()
    {
        local cur=${COMP_WORDS[COMP_CWORD]}
        local prev=${COMP_WORDS[COMP_CWORD-1]}
    
        if [[ $prev == "--sort-direction" ]]; then
            COMPREPLY=( $( compgen -W "horizontal vertical" -- $cur ) )
            return 0
        elif [[ $prev == "--type" ]];then
            COMPREPLY=( $( compgen -W "mammals reptiles birds fish marsupials insects misc" -- $cur ) )
            return 0
        elif [[ $prev == "--size" ]]; then
            COMPREPLY=( $( compgen -W "tiny small medium large huge" -- $cur ) )
            return 0
        fi
    
    
        # completing an option
        if [[ "$cur" == --* ]] || [[ $cur == "" ]]; then
            COMPREPLY=( $( compgen -W "--sort-direction --type --size" -- $cur ) )
        fi
    }
    complete -F _listanimals listanimals
    

    现在我可以做到:

    $ listanimals --[TAB][TAB]
    --size            --sort-direction  --type
    $ listanimals --t[TAB]
    

    它将自动填写:

    $ listanimals --type
    

    然后我可以这样做:

    $ listanimals --type [TAB][TAB]
    birds       fish        insects     mammals     marsupials  misc        reptiles
    

    我相信你能解决剩下的问题。这是一个有效的示例,因此如果您想尝试它,只需将它复制/粘贴到一个文件(例如sample.sh)中,并将其源代码保存在bash中 source sample.sh . 你实际上不需要一个名为listanimals的脚本。

    希望有人会觉得这很有用,因为我觉得很难搞清楚。