도움말 매개변수가 있는 쉘 getopt

도움말 매개변수가 있는 쉘 getopt

대본을 준비 중이에요 getopt. 도움말 섹션을 추가하고 싶습니다. 따라서 함수를 사용 --help하거나 -h실행해야 하는 경우(설명만 인쇄) 반환합니다.

샘플 코드:


log_type='unset'
state='unset'
date='unset'
help='unset'


mode="$1"
usage()
{
  echo "Usage: LogRotator [ -t | --log_type  - Allowed values: [access error] ] 
                          [ -s | --state - Allowed values: [archive or backup] ]
                          [ -d | --date 1-10-2020] 
                          [ -h | --help]

        Modes:
            1) list - list the files
            2) restore  - restore the files"
  exit 2
}


ARGUMENT_LIST=(
    "log-type"
    "state"
    "date"
)



# read arguments
opts=$(getopt \
    --longoptions "$(printf "%s:," "${ARGUMENT_LIST[@]}")",help \
    --name "$(basename "$0")" \
    --options "" \
    -- "$@"
)

VALID_ARGUMENTS=$?
if [ "$VALID_ARGUMENTS" != "0" ]; then
  usage
fi

eval set --$opts

while [[ $# -gt 0 ]]; do
    case "$1" in
        -t | --log-type)
            log_type=$2
            shift 2
            ;;

        -s | --state)
            state=$2
            shift 2
            ;;

        -d | --date)
        date=$2
        shift 2
        ;;

        -h | --help)
        help=1
        shift 
        ;;
        *)
        break
        ;;
    esac
done

if [[ "$help" == 1 ]]
then
    usage
fi

위 스크립트는 잘 작동하지만 using 함수를 확인하고 호출하기 위해 별도의 섹션을 추가했는데 이것이 좋은 방법인지는 잘 모르겠습니다.

-또한 또 다른 문제는 단일 플래그(예: -h -t)를 허용하지 않는다는 것입니다.

나는 -o tsdh성공하지 않고 추가하려고 시도했습니다.

예상 출력:

./script -h

Usage: LogRotator [ -t | --log_type  - Allowed values: [access error] ] 
                          [ -s | --state - Allowed values: [archive or backup] ]
                          [ -d | --date 1-10-2020] 

        Modes:
            1) list - list the files
            2) restore  - restore the files

답변1

나는 이것을 코드 리뷰로 작성했습니다:

첫째, Shebang을 지정하지 않았습니다. Shebang이 없으면 스크립트는 에 의해 작성됩니다 sh. 귀하의 코드는 문법적이지 않습니다 sh. 가장 유사한 구문을 가진 쉘은 입니다 . 그러나 zsh인용되지 않은 경우 $optsksh93 및 bash에서도 작동합니다 . 나는 zsh그것을 작성하는 더 좋은 방법이 있을 것이기 때문에 bash용으로 설계되었다고 생각합니다 .

그래서 여기 있습니다:

#! /bin/bash -

또는:

#! /usr/bin/env bash

지원이 bash불가능합니다 /bin.

log_type='unset'
state='unset'
date='unset'
help='unset'

여기서 특정 문자열을 기본값으로 사용하면 사용자가 옵션을 지정하지 않았는데 값이 로 되어 있는 상황을 없앨 수는 없습니다 unset.

여기서는 그냥 하고 싶어요

unset -v log_type state date help

부울 값의 경우 help=false.

mode="$1"

여기에서 첫 번째 인수를 저장 $mode하지만 존재하는지 확인하지 않거나 인수 목록에서 제거합니다. 즉, getopt인수도 받게 됩니다!

아마도:

  case $1 in
    (list | restore) mode=$1; shift;;
    (*) usage;;
  esac

(함수 선언 후 usage).

usage()
{
  echo "Usage: LogRotator [ -t | --log_type  - Allowed values: [access error] ] 
                          [ -s | --state - Allowed values: [archive or backup] ]

이러한 [ -t합계는 [ -s스크립트의 소스 코드에서 정렬되지만 들여쓰기로 인해 출력에는 표시되지 않습니다. 또한 here 와 같이 스크립트 이름을 하드코딩 LogRotator하지만 basename나중에 사용합니다. $0또한 사용법 메시지는 stderr로 전송되어야 합니다.

PROGNAME=${0##*/}

usage() {
  cat << EOF >&2
Usage: $PROGNAME ...
EOF
                          [ -d | --date 1-10-2020] 

이것은 1-10-2020아마도 최악의 날짜 형식일 것입니다. 첫째, 모호합니다. 대부분의 사람들은 이를 10월 1일로 이해하지만 북미 일부 지역에서는 1월 10일로 이해합니다. 또한 이러한 문자열을 시간순으로 정렬하는 것은 어휘순으로 정렬하는 것과 다릅니다(필드 순서를 변경한 후에도 해당 부분이 0으로 채워지지 않기 때문에).

날짜는 국제 형식을 갖습니다. 2020-10-01은 대부분의 인력 및 유틸리티 회사에서 인정하는 표준이 될 것이며, 연대순과 어휘순으로 동일하게 정렬됩니다.

[...]

ARGUMENT_LIST=(
    "log-type"
    "state"
    "date"
)

모든 대문자 변수를 유지하는 것이 좋습니다환경변하기 쉬운.

# read arguments
opts=$(getopt \
    --longoptions "$(printf "%s:," "${ARGUMENT_LIST[@]}")",help \

:,여기서는 모든 요소에 추가하여 $ARGUMENT_LIST얻을 수 있습니다 log-type:,state:,date:,,help.

    --name "$(basename "$0")" \

"$(basename -- "$0"}"아니면 여기 여야 합니다 ${0##*/}. 이것이 "$PROGNAME"우리가 앞서 정의한 것입니다.

    --options "" \

이는 단일 문자 옵션에 대한 것이므로 여기에서 지정해야 합니다.

  --options hs:d:t:
    -- "$@"
)

VALID_ARGUMENTS=$?
if [ "$VALID_ARGUMENTS" != "0" ]; then

if명령이 성공했는지 확인하십시오. 그것이 바로 그 일입니다.

그래서 그냥:

   if 
     ! opts=$(
       ...
     )
   then
     usage
   fi

그렇지 않으면:

   opts=$(...) || usage

여기.

  usage
fi

eval set --$opts

따옴표가 없는 인수 확장은 분할+glob을 호출하는데, 이는 여기서는 의미가 없습니다. 또한 --여기서는 나머지 항목과 분리 해야 합니다 . 이것이 set -- <contents-of-$opts>쉘 코드로 평가되기를 원하는 것입니다.

   eval "set -- $opts"
while [[ $# -gt 0 ]]; do
    case "$1" in
        -t | --log-type)
            log_type=$2

사용된 경우 사용자에게 경고하려면 여기에 허용된 설정과 비교하여 제공된 값을 확인해야 합니다 -t blah -t error. 또한 마지막으로 지정된 유형만 고려된다는 점을 사용자에게 경고할 수도 있습니다.

            shift 2
            ;;

        -s | --state)
            state=$2
            shift 2
            ;;

        -d | --date)
        date=$2

들여쓰기에 주의하세요. 일관된 들여쓰기는 코드를 더 읽기 쉽게 만들고 일부 오류를 방지하는 데 도움이 됩니다.

        shift 2
        ;;

        -h | --help)
        help=1
        shift 
        ;;
        *)
        break

옵션이 끝나는 위치를 알려주기 위해 하나가 추가되었기 shift; break때문에 여기에 있어야 합니다 .getopt--

        ;;
    esac
done

이 시점에서 더 많은 매개변수를 사용할 수 있는지 확인하고 예상과 다르면 오류를 보고할 수 있습니다.

  [ "$#" -eq 0 ] || usage
if [[ "$help" == 1 ]]
then
    usage
fi

help=false/를 사용했다면 help=true다음과 같습니다.

  if "$help"; then
    usage
  fi

답변2

에 짧은 옵션을 추가하여 스크립트를 수정했습니다 getopt. :각 옵션 뒤에는 opt옵션에 인수가 필요하다는 의미가 있습니다.

#!/bin/bash
log_type='unset'
state='unset'
date='unset'
help='unset'


mode="$1"
usage()
{
  echo "Usage: LogRotator [ -t | --log_type  - Allowed values: [access error] ] 
                          [ -s | --state - Allowed values: [archive or backup] ]
                          [ -d | --date 1-10-2020] 
                          [ -h | --help]

        Modes:
            1) list - list the files
            2) restore  - restore the files"
  exit 2
}


ARGUMENT_LIST=(
    "log-type"
    "state"
    "date"
)



# read arguments
opts=$(getopt \
    -o t:s:d:h \
    --longoptions "$(printf "%s:," "${ARGUMENT_LIST[@]}")",help \
    --name "$(basename "$0")" \
    -- "$@"
)

VALID_ARGUMENTS=$?
if [ "$VALID_ARGUMENTS" != "0" ]; then
  usage
fi

eval set -- $opts

while [[ $# -gt 0 ]]; do
    case "$1" in
        -t | --log-type)
            log_type=$2
            shift 2
            ;;

        -s | --state)
            state=$2
            shift 2
            ;;

        -d | --date)
        date=$2
        shift 2
        ;;

        -h | --help)
        help=1
        shift
        ;;
        *)
        break
        ;;
    esac
done

if [[ "$help" == 1 ]]
then
    usage
fi

관련 정보