2013-06-10 4 views
2

두 개의 필수 인수 (arg1, arg2)가있는 쉘 스크립트를 작성한 다음 선택적 -b 플래그와 사용자가 플래그를 사용하도록 선택해야하는 인수를 더한 쉘 스크립트를 작성하려고합니다.BASH getopts 선택적 인수

설명해 드리죠 :

그것은 Github의 저장소에서 응용 프로그램을 가져 GIT의 이점을 취하는 설치 스크립트입니다. 사용자가 터미널 f.ex에 입력합니다. :

이 스크립트는이 저장소에서 master 브랜치의 인스턴스를 가져옵니다. 그러나 사용자가 선택적 -b 플래그를 사용하도록 선택해야합니다. 즉, 가져올 브랜치를 지정하려고 함을 의미합니다. 가지를 개발하라. 사용자가 할 수있는 것을 의미 :

./shellscript.sh new <app_name> -b develop # or which ever branch there is available 

그것은 중요하지 않을 수 있도록 나는 또한 당신이 스크립트 작업을 만드는 방법에 대한 갈 수 있는지 궁금 경우 '새로운 전 -b 플래그 + branch_name에서 사용자 유형 '인수와'app_name '인수가 있습니다. 그러나 그것은 아마도 현재 가장 중요한 것은 아닙니다. My Super Cool Artisan Executable Script

PS :

내가 구축을 위해 노력하고있어 정확히 알고, 여기에만 두 개의 필수 인수를 만 마스터 분기 가져 오는 나의 현재 스크립트에 대한 링크입니다 나는 시도했습니다 나는 Stackoverflow와 그 밖의 다른 블로그에서 발견 한 getopts를 사용하는 많은 예제를 제공하지만 아무도 완전히 작동하게 만들지 못했습니다. 따라서 저는 여기서 위대한 사람들에게 도움을 청합니다.

거대한 덕분에 내 Linux Mint/Ubuntu - Post Install Script for only cool people(you guys and those switching over to Linux from Windows/Mac)

안부를 확인해야 융모는

+0

코드 삽입 시도되었습니다. – TrueY

답변

5

나는 일반적으로 짧고 긴 옵션을 할 수 있도록 내 자신을 쓰기 :

function Usage() 
{ 
cat <<-ENDOFMESSAGE 

$0 [OPTION] REQ1 REQ2 

options: 

    -b -branch branch to use 
    -h --help display this message 

ENDOFMESSAGE 
    exit 1 
} 

function Die() 
{ 
    echo "$*" 
    exit 1 
} 

function GetOpts() { 
    branch="" 
    argv=() 
    while [ $# -gt 0 ] 
    do 
     opt=$1 
     shift 
     case ${opt} in 
      -b|--branch) 
       if [ $# -eq 0 -o "${1:0:1}" = "-" ]; then 
        Die "The ${opt} option requires an argument." 
       fi 
       branch="$1" 
       shift 
       ;; 
      -h|--help) 
       Usage;; 
      *) 
       if [ "${opt:0:1}" = "-" ]; then 
        Die "${opt}: unknown option." 
       fi 
       argv+=(${opt});; 
     esac 
    done 
} 

GetOpts $* 
echo "branch ${branch}" 
echo "argv ${argv[@]}" 
+0

나는 당신의 접근 방식을 좋아합니다. 나는 이것을 시험 할 것이다. 고맙습니다! –

+0

+1'argv + = ($ {opt})'에 +1! – TrueY

2

유닉스 유틸리티가 정상적으로 수행 선택적 인자 ("flags") 전에 위치 인수. C 라이브러리 함수 GNU 구현을 포함한 대부분의 GNU 유틸리티 getopt, 선택적 인수가 먼저 나오도록 명령 줄 인수를 섞습니다. 그러나 bash 내장 된 getopts은 셔플을하지 않으므로 원하는 경우 할 수 있습니다.

getopts은 항상 숫자가 변수 OPTIND의 값인 인수로 시작합니다. (OPTIND는 bash 함수가 실행될 때마다 1로 설정되고 전역 변수이므로 서로 호출하는 bash 함수에는주의가 필요합니다.) 원하는 경우 OPTIND를 직접 설정할 수 있으며 다음 getopts으로 전화하면 해당 색인으로 시작합니다. 또는 shift을 사용하여 모든 명령 줄 인수를 이동할 수 있습니다.

따라서, 예를 들어, 당신이 할 수 있습니다 :

# "shift" version: always shift consumed arguments 
local verb="$1" branch=master app_name option 
shift 
case $verb in 
    new) app_name="$1" 
     shift 
     while getopts b: option; do 
      case $option in 
      b) branch=$OPTARG;; 
      *) # handle the error;; 
      esac 
     done 
     shift $((OPTIND - 1));; 
    *) # handle the error or other subcommands;; 
esac 
# At this point, there are still arguments if ((OPTIND > 0)) 

또는 :

# non-shift version: use OPTIND to index arguments 
local verb="${!OPTIND}" branch=master app_name option 
OPTIND=$((OPTIND + 1)) 
case $verb in 
    new) app_name="${!OPTIND}" 
     OPTIND=$((OPTIND + 1)) 
     while getopts b: option; do 
      case $option in 
      b) branch=$OPTARG;; 
      *) # handle the error;; 
      esac 
     done;; 
    *) # handle the error or other subcommands;; 
esac 
# At this point, there are still arguments if ((OPTIND > $#)) 
+0

안녕하세요 @rici, 당신의 솔루션은 매우 유망 해 보입니다. 이 오류가 발생해도 "local : 함수에서만 사용할 수 있습니다". 어떻게 이것에 대해 가겠습니까? 감사합니다! –

+0

함수에 넣거나 로컬 선언을 선택하지 않아도됩니다. 나는 프로그램을 함수로 분해하는 것을 좋아하지만, YMMV. 지역 선언을 제거하면 변수를 초기화해야합니다. – rici

+0

+1! '$ {! OPTIND}'는 나에게 새로운 것이었다! IMHO'OPTIND = ((OPTIND + 1))'이 올바르지 않습니다. 'OPTIND = $ ((OPTIND + 1))'또는'((OPTIND = OPTIND + 1))'또는 단순히'((++ OPTIND))'가 작동합니다. – TrueY

1

을 조금 단순화 된 버전을 getopts 오류보고 할 수있는 사용 :

#!/usr/bin/bash 

help() { echo -e "Usage\n\t$0: new <app_name> [-b <develop>]" >&2;} 
die() { [ -n "$1" ] && echo -e "Error: $1\n" >&2; help; [ -z "$1" ]; exit;} 

[ $# -lt 2 ] && die "Too few args" 
[ $1 != "new" ] && die "Bad first arg ($1)" 
app_name=$2 
shift 2 

unset develop 
while getopts "b:" opt; do 
    case $opt in 
    \?) exit 1;; 
    b) develop="$OPTARG";; 
    esac 
done 

echo "app_name: $app_name, develop: $develop" 

을 테스트 :

$./test new App 
app_name: App, develop: 
$./test new App -b Dev 
app_name: App, develop: Dev 

어쨌든 인수 전달의 표준 방법을 사용하는 것이 좋습니다. new 대신 -n을 사용할 수 있습니다.