Bash Shell Script-플래그를 확인하고 값을 가져옵니다.


80

다음과 같이 실행되도록 설계된 쉘 스크립트를 만들려고합니다.

script.sh -t application

첫째, 스크립트에서 스크립트가 -t 플래그로 실행되었는지 확인하고 싶습니다. 예를 들어 다음과 같은 플래그없이 실행 된 경우 오류가 발생합니다.

script.sh

둘째, -t 플래그가 있다고 가정하면 값을 가져 와서 다음과 같이 스크립트에서 사용할 수있는 변수에 저장하고 싶습니다.

FLAG="application"

지금까지 내가 할 수 있었던 유일한 진전은 $ @가 모든 명령 줄 인수를 잡는다는 것입니다. 그러나 이것이 플래그와 어떤 관련이 있는지 또는 이것이 가능한지 모르겠습니다.


답변:


128

getopts 자습서를 읽어야합니다 .

-a인수가 필요한 스위치의 예 :

#!/bin/bash

while getopts ":a:" opt; do
  case $opt in
    a)
      echo "-a was triggered, Parameter: $OPTARG" >&2
      ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
      exit 1
      ;;
    :)
      echo "Option -$OPTARG requires an argument." >&2
      exit 1
      ;;
  esac
done

그레이 봇이 말했듯이 ( getopt! = getopts) :

당신이하지 않으면 외부 명령 getopt는 (1), 사용하는 것이 결코 안전 을 알고 는 GNU의 getopt는, 당신은 GNU 특정 방식으로 호출, 그리고 당신은 GETOPT_COMPATIBLE 환경에 있지 않은지 확인합니다. 대신 getopts (쉘 내장)를 사용하거나 단순히 위치 매개 변수를 반복하십시오.


1
getoptsA는 bash내장하지만, 외부도있다 getopt모든 POSIX 호환 쉘과 함께 작동합니다 프로그램.
chepner

3
당신이하지 않으면 외부 명령 getopt는 (1), 사용하는 것이 결코 안전 을 알고 는 GNU의 getopt는, 당신은 GNU 특정 방식으로 호출, 그리고 당신은 GETOPT_COMPATIBLE 환경에 있지 않은지 확인합니다. 대신 getopts (쉘 내장)를 사용하거나 단순히 위치 매개 변수를 반복하십시오.
Gilles Quenot 2013 년

미안해. 이 떠들썩한 파티가 내장되어있는 경우는 데비안에서 쉘 작동합니다
지미

getopts튜토리얼은 간단하고 유용한 예제를 제공합니다. 이 게시물을 발견하면 확실히 읽을 가치가 있습니다.
Steven C. Howell

이전 의견에 동의 : getopts 자습서는 주석을 포함하여 읽는 데 시간을 할애 할 가치가 있습니다.이 중 일부는 고급 / 대체 사용법을 제공합니다.
François POYER

32

사용 $#제공 충분한 인수가없는 것이이 같지 않은 경우, 인수의 수를 잡아 :

if [ $# -ne 2 ]; then
   usage;
fi

다음으로 $1같지 않은지 확인하십시오 -t. 그렇지 않으면 알 수없는 플래그가 사용되었습니다.

if [ "$1" != "-t" ]; then
  usage;
fi

마지막으로 저장 $2에서 FLAG:

FLAG=$2

참고 : usage()구문을 보여주는 일부 기능입니다. 예를 들면 :

function usage {
   cat << EOF
Usage: script.sh -t <application>

Performs some activity
EOF
   exit 1
}

작동 할 수 있지만 여러 플래그를 사용하려면 어떻게됩니까?
killjoy

더 복잡해지고 다음에 설명 된대로 getopts 명령을 사용하는 것이 더 합리적입니다. @GillesQuenot의 대답
Veger

11

다음은 모든 스크립트의 맨 위에 붙여 넣을 수있는 일반화 된 간단한 명령 인수 인터페이스입니다.

#!/bin/bash

declare -A flags
declare -A booleans
args=()

while [ "$1" ];
do
    arg=$1
    if [ "${1:0:1}" == "-" ]
    then
      shift
      rev=$(echo "$arg" | rev)
      if [ -z "$1" ] || [ "${1:0:1}" == "-" ] || [ "${rev:0:1}" == ":" ]
      then
        bool=$(echo ${arg:1} | sed s/://g)
        booleans[$bool]=true
        echo \"$bool\" is boolean
      else
        value=$1
        flags[${arg:1}]=$value
        shift
        echo \"$arg\" is flag with value \"$value\"
      fi
    else
      args+=("$arg")
      shift
      echo \"$arg\" is an arg
    fi
done


echo -e "\n"
echo booleans: ${booleans[@]}
echo flags: ${flags[@]}
echo args: ${args[@]}

echo -e "\nBoolean types:\n\tPrecedes Flag(pf): ${booleans[pf]}\n\tFinal Arg(f): ${booleans[f]}\n\tColon Terminated(Ct): ${booleans[Ct]}\n\tNot Mentioned(nm): ${boolean[nm]}"
echo -e "\nFlag: myFlag => ${flags["myFlag"]}"
echo -e "\nArgs: one: ${args[0]}, two: ${args[1]}, three: ${args[2]}"

다음 명령을 실행합니다.

bashScript.sh firstArg -pf -myFlag "my flag value" secondArg -Ct: thirdArg -f

출력은 다음과 같습니다.

"firstArg" is an arg
"pf" is boolean
"-myFlag" is flag with value "my flag value"
"secondArg" is an arg
"Ct" is boolean
"thirdArg" is an arg
"f" is boolean


booleans: true true true
flags: my flag value
args: firstArg secondArg thirdArg

Boolean types:
    Precedes Flag(pf): true
    Final Arg(f): true
    Colon Terminated(Ct): true
    Not Mentioned(nm): 

Flag: myFlag => my flag value

Args: one => firstArg, two => secondArg, three => thirdArg

기본적으로 인수는 플래그 부울 및 일반 인수로 나뉩니다. 이렇게하면 사용자가 지정된 순서대로 일반 인수 (있는 경우)를 유지하는 한 플래그와 부울을 어디에나 둘 수 있습니다.

저와 지금은 bash 인수 구문 분석을 다시는 다루지 않도록 허용합니다!

여기 에서 업데이트 된 스크립트를 볼 수 있습니다.

이것은 작년에 엄청나게 유용했습니다. 이제 변수 앞에 범위 매개 변수를 붙여 범위를 시뮬레이션 할 수 있습니다.

다음과 같이 스크립트를 호출하십시오.

replace() (
  source $FUTIL_REL_DIR/commandParser.sh -scope ${FUNCNAME[0]} "$@"
  echo ${replaceFlags[f]}
  echo ${replaceBooleans[b]}
)

인수 범위를 구현 한 것처럼 보이지 않지만 아직 필요하지 않은 이유가 확실하지 않습니다.


2
이것은 훌륭한 대답입니다. 스크립트에 배치하고 .bashrc 파일에서 arg_handler로 별칭을 지정하여 한 단계 더 나아갑니다. 그런 다음 모든 스크립트의 맨 위에 붙여 넣습니다.source arg_handler; arg_handler "$@"
J.Warren

-pf는 두 개의 대시로 진행되지 않기 때문에 두 개의 개별 플래그 여야하지 않습니까? p와 f에서와 같이.
James Trickey

1

shFlags-Unix 셸 스크립트 용 고급 명령 줄 플래그 라이브러리를 사용해보십시오.

http://code.google.com/p/shflags/

매우 훌륭하고 매우 유연합니다.

FLAG TYPES : 이것은 당신이 할 수있는 DEFINE_ *의 목록입니다. 모든 플래그는 이름, 기본값, 도움말 문자열 및 선택적 '짧은'이름 (한글자 이름)을 사용합니다. 일부 플래그에는 플래그로 설명되는 다른 인수가 있습니다.

DEFINE_string : 모든 입력을 받아 문자열로 해석합니다.

DEFINE_boolean : 일반적으로 인수를 사용하지 않습니다. FLAGS_myflag를 true로 설정하려면 --myflag를, FLAGS_myflag를 false로 설정하려면 --nomyflag라고 말하세요. 또는 --myflag = true 또는 --myflag = t 또는 --myflag = 0 또는 --myflag = false 또는 --myflag = f 또는 --myflag = 1이라고 말할 수 있습니다. 옵션을 전달하는 것은 옵션을 한 번.

DEFINE_float : 입력을 받아 부동 소수점 숫자로 해석합니다. 쉘은 부동 소수점을 지원하지 않기 때문에 입력은 유효한 부동 소수점 값으로 만 검증됩니다.

DEFINE_integer : 입력을 받아 정수로 해석합니다.

특수 플래그 : 특별한 의미를 가진 몇 가지 플래그가 있습니다. --help (또는-?)는 사람이 읽을 수있는 방식으로 모든 플래그 목록을 인쇄합니다 .-- flagfile = foo foo에서 플래그를 읽습니다. (아직 구현되지 않음)-getopt ()에서와 같이 플래그 처리를 종료합니다.

사용 예 :

-- begin hello.sh --
 ! /bin/sh
. ./shflags
DEFINE_string name 'world' "somebody's name" n
FLAGS "$@" || exit $?
eval set -- "${FLAGS_ARGV}"
echo "Hello, ${FLAGS_name}."
-- end hello.sh --

$ ./hello.sh -n Kate
Hello, Kate.

참고 :이 텍스트는 shflags 문서에서 가져 왔습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.