자동 완성 기능으로 스크립트를 작성하는 방법은 무엇입니까?


119

프로그램을 사용 svn하고 그놈 터미널에 입력 하면 :

svn upd

다음과 같이 Tab자동 완성됩니다.

svn update

내 사용자 정의 bash 스크립트에서 이와 같은 작업을 수행 할 수 있습니까?


스크립트를 편집 할 때 "bash script"를 설명 하시겠습니까? 그것으로 무엇을하고 싶습니까?
Bruno Pereira

3
콘솔에서 스크립트를 사용할 때
UAdapter

수료 장소는 이 질문 과 그에 대한 답변을 참조하십시오 .
jarno

답변:


44

Programmable Completion을 사용할 수 있습니다 . 에서 찾아 보게 /etc/bash_completion하고 /etc/bash_completion.d/*몇 가지 예를 들어.


130
질문과 직접 ​​관련된 간단한 예를 포함시키는 것은 어떻습니까?
MountainX

2
Ubuntu 16의 실제 스크립트는/usr/share/bash-completion/completions/<program>
Peter

16
이모, 예제는 링크가 아닌 답변에 포함되어야합니다.
billynoah

2
나는이 플랫폼이 간단한 구글 검색으로 찾을 수있는 전체 문서에 대한보다 실용적인 대안이라고 생각합니다. 문서 링크를 덤프해도 도움이되지 않습니다. 앵커를 포함하는 링크는 큰 차이가 없습니다.
timuçin

4
The provided link has that already-오늘 일 수도 있지만 내일은 아닐 수도 있습니다. 또는 내년에. 또는 10 년 안에. 설명서가 여전히 관련성이 있다고 제안 할 수 있더라도 Stack Overflow는 이러한 이유로 링크 전용 답변을 권장하지 않습니다.
리암 도슨

205

나는 6 개월 늦었지만 같은 것을 찾고 있었고 이것을 발견했습니다.

새 파일을 만들어야합니다 :

/etc/bash_completion.d/foo

정적 자동 완성 (예 : --help/ --verbose)의 경우 다음을 추가하십시오.

_foo() 
{
    local cur prev opts
    COMPREPLY=()
    cur="${COMP_WORDS[COMP_CWORD]}"
    prev="${COMP_WORDS[COMP_CWORD-1]}"
    opts="--help --verbose --version"

    if [[ ${cur} == -* ]] ; then
        COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
        return 0
    fi
}
complete -F _foo foo
  • COMP_WORDS 현재 명령 행의 모든 ​​개별 단어를 포함하는 배열입니다.
  • COMP_CWORD 현재 커서 위치를 포함하는 단어의 색인입니다.
  • COMPREPLY Bash가 가능한 완료를 읽는 배열 변수입니다.

그리고 compgen명령의 요소의 배열 반환 --help, --verbose그리고 --version현재 단어와 일치를 "${cur}":

compgen -W "--help --verbose --version" -- "<userinput>"

출처 : http://www.debian-administration.org/articles/316


27
이것이 정답입니다! 완전한 예입니다.
Victor Schröder

5
팁 : 누군가 단어로 시작하지 않는 단어에 대한 제안을 원 -하고 대상 단어를 입력하지 않아도 단어를 표시하려면 if [...] thenfi행을 제거하십시오 .
Cedric Reichenbach

1
이것은 내가 몇 시간 동안 찾은 정확한 답변이며, 파일을 배치해야한다는 언급이없는 복잡한 문서에서 익사 한 것으로 나타났습니다 /etc/bash_completion.d/. 나는 어딘가에 답을 게시하고 싶었 기 때문에 여기에 왔지만 누군가가 3 년 앞서 있다고 밝혀졌습니다.) 명확하고 간결하며 완전한 예, 감사합니다!
Steen Schütt

1
튜토리얼
-bash

34

모든 bash 완료는에 저장됩니다 /etc/bash_completion.d/. 따라서 bash_completion을 사용하여 소프트웨어를 빌드하는 경우 deb / make 설치시 해당 디렉토리의 소프트웨어 이름으로 파일을 삭제하는 것이 좋습니다. 다음은 Rsync에 대한 bash 완료 스크립트 예입니다.

# bash completion for rsync

have rsync &&
_rsync()
{
    # TODO: _split_longopt

    local cur prev shell i userhost path   

    COMPREPLY=()
    cur=`_get_cword`
    prev=${COMP_WORDS[COMP_CWORD-1]}

    _expand || return 0

    case "$prev" in
    --@(config|password-file|include-from|exclude-from))
        _filedir
        return 0
        ;;
    -@(T|-temp-dir|-compare-dest))
        _filedir -d
        return 0
        ;;
    -@(e|-rsh))
        COMPREPLY=( $( compgen -W 'rsh ssh' -- "$cur" ) )
        return 0
        ;;
    esac

    case "$cur" in
    -*)
        COMPREPLY=( $( compgen -W '-v -q  -c -a -r -R -b -u -l -L -H \
            -p -o -g -D -t -S -n -W -x -B -e -C -I -T -P \
            -z -h -4 -6 --verbose --quiet --checksum \
            --archive --recursive --relative --backup \
            --backup-dir --suffix= --update --links \
            --copy-links --copy-unsafe-links --safe-links \
            --hard-links --perms --owner --group --devices\
            --times --sparse --dry-run --whole-file \
            --no-whole-file --one-file-system \
            --block-size= --rsh= --rsync-path= \
            --cvs-exclude --existing --ignore-existing \
            --delete --delete-excluded --delete-after \
            --ignore-errors --max-delete= --partial \
            --force --numeric-ids --timeout= \
            --ignore-times --size-only --modify-window= \
            --temp-dir= --compare-dest= --compress \
            --exclude= --exclude-from= --include= \
            --include-from= --version --daemon --no-detach\
            --address= --config= --port= --blocking-io \
            --no-blocking-io --stats --progress \
            --log-format= --password-file= --bwlimit= \
            --write-batch= --read-batch= --help' -- "$cur" ))
        ;;
    *:*)
        # find which remote shell is used
        shell=ssh
        for (( i=1; i < COMP_CWORD; i++ )); do
            if [[ "${COMP_WORDS[i]}" == -@(e|-rsh) ]]; then
                shell=${COMP_WORDS[i+1]}
                break
            fi
        done
        if [[ "$shell" == ssh ]]; then
            # remove backslash escape from :
            cur=${cur/\\:/:}
            userhost=${cur%%?(\\):*}
            path=${cur#*:}
            # unescape spaces
            path=${path//\\\\\\\\ / }
            if [ -z "$path" ]; then
                # default to home dir of specified
                # user on remote host
                path=$(ssh -o 'Batchmode yes' $userhost pwd 2>/dev/null)
            fi
            # escape spaces; remove executables, aliases, pipes
            # and sockets; add space at end of file names
            COMPREPLY=( $( ssh -o 'Batchmode yes' $userhost \
                command ls -aF1d "$path*" 2>/dev/null | \
                sed -e 's/ /\\\\\\\ /g' -e 's/[*@|=]$//g' \
                -e 's/[^\/]$/& /g' ) )
        fi
        ;;
    *)  
        _known_hosts_real -c -a "$cur"
        _filedir
        ;;
    esac

    return 0
} &&
complete -F _rsync $nospace $filenames rsync

# Local variables:
# mode: shell-script
# sh-basic-offset: 4
# sh-indent-comment: t
# indent-tabs-mode: nil
# End:
# ex: ts=4 sw=4 et filetype=sh

프로그램과 가장 일치하는 bash 완성 파일 중 하나를 검토하는 것이 좋습니다. 가장 간단한 예 중 하나는 rrdtool파일입니다.


2
다른 위치에서로드하도록 완료를 구성 할 수 있습니까? IE. ~ / .local
Chris

1
예, 원하는 곳 source ~/.local/mycrazycompletion에서 다음과 같은 파일을 넣을 수 있습니다.~/.bashrc
Stefano Palazzo


현재 대부분의 완료는 pkg-config --variable = completionsdir bash-completion` 명령으로 제공된 디렉토리에 있으며 해당 디렉토리는 위의 Bash Completion FAQ에서 제공하는 권장 사항입니다.
jarno

33

다음은 완전한 자습서입니다.

자동 완성 기능을 사용하려는 admin.sh라는 스크립트 예제를 사용할 수 있습니다.

#!/bin/bash

while [ $# -gt 0 ]; do
  arg=$1
  case $arg in
    option_1)
     # do_option_1
    ;;
    option_2)
     # do_option_1
    ;;
    shortlist)
      echo option_1 option_2 shortlist
    ;;
    *)
     echo Wrong option
    ;;
  esac
  shift
done

옵션 명단을 참고하십시오. 이 옵션으로 스크립트를 호출하면이 스크립트에 가능한 모든 옵션이 인쇄됩니다.

그리고 여기 자동 완성 스크립트가 있습니다 :

_script()
{
  _script_commands=$(/path/to/your/script.sh shortlist)

  local cur
  COMPREPLY=()
  cur="${COMP_WORDS[COMP_CWORD]}"
  COMPREPLY=( $(compgen -W "${_script_commands}" -- ${cur}) )

  return 0
}
complete -o nospace -F _script ./admin.sh

마지막으로 완료 할 인수는 자동 완성을 추가하려는 스크립트의 이름입니다. 다음과 같이 자동 완성 스크립트를 bashrc에 추가하기 만하면됩니다.

source /path/to/your/autocomplete.sh

또는 /etc/bash.completion.d에 복사하십시오.


1
prev변수 는 무엇입니까 ? 당신은 그것을 사용하지 않는 것 같습니다.
dimo414

@ dimo414 그렇게 보인다, 나는 그 변수를 제거했다
kokosing

뭐라고합니까 -o nospace옵션은 무엇입니까?
앤드류 라 마라

11

원하는 것이 간단한 단어 기반 자동 완성 (따라서 하위 명령 완료 등)이면 complete명령 -W에 올바른 작업을 수행 하는 옵션이 있습니다.

예를 들어 jupyter.bashrc 라는 프로그램을 자동 완성하는 데 다음 줄이 있습니다 .

# gleaned from `jupyter --help`
_jupyter_options='console qtconsole notebook' # shortened for this answer
complete -W "${_jupyter_options}" 'jupyter'

이제 jupyter <TAB> <TAB>자동 완성 기능이 있습니다.

gnu.org 의 문서 가 도움이됩니다.

IFS변수가 올바르게 설정되어 있는 것처럼 보이지만 나에게 아무런 문제가되지 않았습니다.

파일 이름 완성과 기본 BASH 완성을 추가하려면 다음 -o옵션을 사용하십시오 .

complete -W "${_jupyter_options}" -o bashdefault -o default 'jupyter'

zsh에서 이것을 사용하려면에서 complete명령을 실행하기 전에 다음 코드를 추가 하십시오 ~/.zshrc.

# make zsh emulate bash if necessary
if [[ -n "$ZSH_VERSION" ]]; then
    autoload bashcompinit
    bashcompinit
fi

이 작업을 어떻게 수행 bash jupyter <TAB><TAB>합니까?
papampi

@papampi, 나는 그것이 한 단계의 완성에서만 작동한다고 생각합니다. 위의 더 복잡한 답변 중 하나가 필요한 2 개의 레이어로 처리한다고 생각합니다. 또한 최근에는 bash 완료에 대한 꽤 괜찮은 자습서를 읽었습니다 . 필요한 것을 정확하게 수행하지는 않지만 도움이 될 수 있습니다. 행운을 빕니다!
Ben
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.