getopts에 옵션이 지정되지 않은 경우 기본 옵션 실행

getopts에 옵션이 지정되지 않은 경우 기본 옵션 실행

나는 튜토리얼을 따랐다.여기사용 방법을 알아보세요 getopts. 사용자가 제공한 모든 옵션을 올바르게 실행할 수 있습니다. 그런데 이제는 옵션이 제공되지 않을 때 기본 옵션을 실행하고 싶습니다.

예를 들어:

while getopts ":hr" opt; do
    case $opt in
        h )
            show_help;
            exit 1
            ;;
        r )
          echo "Default option executed"
          ;;
    esac
done

따라서 사용자가 또는 을 제공하면 -h해당 -r명령이 실행되어야 하지만(그렇습니다) 이러한 옵션이 제공되지 않으면 -r기본적으로 실행되어야 합니다. 이것을 달성할 수 있는 방법이 있나요?

고쳐 쓰다

cas's제안 사항을 시도 하고 이를 *)getopts기능에 통합했지만 아무 일도 일어나지 않는 것 같습니다.

while getopts ":hr" opt; do
    case $opt in
        h )
            show_help;
            exit 1
            ;;
        r )
          echo "Default option executed"
          ;;

        \? )
          echo error "Invalid option: -$OPTARG" >&2
          exit 1
          ;;

        : )
          echo error "Option -$OPTARG requires an argument."
          exit 1
          ;;

        * )
          echo "Default option executed"
          ;;
    esac
done

이 코드에 문제가 있나요?

답변1

구문 분석할 옵션이 없으면 case문이 실행되지 않으므로 문에 기본 옵션을 추가해도 도움이 되지 않습니다. getopts쉘 변수를 사용하여 얼마나 많은 옵션을 처리하는지 확인할 수 있습니다 OPTIND. 에서 help getopts:

Each time it is invoked, getopts will place the next option in the
shell variable $name, initializing name if it does not exist, and
the index of the next argument to be processed into the shell
variable OPTIND.  OPTIND is initialized to 1 each time the shell or
a shell script is invoked.

따라서 OPTIND1이면 옵션이 처리되지 않습니다. 루프 뒤에 다음을 추가합니다 while.

if (( $OPTIND == 1 )); then
   echo "Default option"
fi

답변2

while옵션이 제공되지 않으면 Bash의 getopts는 $opt를 "?"로 설정하여 루프를 종료합니다. 스크립트에서 이 상황을 확인하려면 다음 과 유사한 루프 if뒤에 절을 추가하세요 .while

if [ "$opt" = "?" ]
then
  echo "Default option executed (by default)"
fi

참고로 다음을 참조하세요.Bourne Shell 내장 함수

답변3

getopts루프를 사용하여 전달된 인수를 기반으로 변수를 설정합니다. 그런 다음 다음 변수에 대해 조치를 취하십시오.

#!/bin/sh

# Defaults:
do_help=0
do_r=0

while getopts "hr" opt; do
    case $opt in
        h) do_help=1 ;;
        r) do_r=1    ;;
        *) echo 'Error in command line parsing' >&2
           exit 1
    esac
done

if [ "$do_help" -eq 1 ]; then
    show_help
    exit
fi

printf 'Default option executed (r=%d)\n' "$do_r"

나는 0이 아닌 종료 상태(도움을 ​​요청하는 것은 오류가 아님)를 사용하는 대신 -h사용 시(실패하지 않는 한) 성공적으로 코드를 종료하도록 선택했습니다 .show_help

실행하세요:

$ sh script.sh -r
Default option executed (r=1)
$ sh script.sh
Default option executed (r=0)
$ sh script.sh -h
script.sh[24]: show_help: not found

이는 명령줄 구문 분석 코드를 나머지 스크립트 논리와 분리하는 이점이 있습니다.

또한 실제 구문 분석 루프를 짧게 유지하면서 루프 후에 기본적인 온전성 검사를 수행할 수 있습니다. 예를 들어:

# command line parsing loop above here

if [ "$do_help" -eq 1 ] && [ "$do_r" -eq 1 ]; then
    echo 'Options -h and -r are mutually exclusive' >&2
    exit 1
fi

# code that acts on user-supplied options below

답변4

내가 아는 한, r은 인수를 기대하지 않습니다. 논리적으로 r은 무슨 일이 일어나더라도 동일한 방식으로 수행됩니다.

getopts 절에서 r 관련 명령을 가져와 실행하도록 하겠습니다. 나는 이것이 귀하의 요구 사항에 충분하다고 믿습니다. 즉, "done" 문 뒤에 echo 문을 배치하세요.

호환성이나 다른 이유로 r을 원하는 경우 getopts에서 r을 스텁으로 유지할 수 있습니다.

0으로 설정된 변수를 스위치로 추가할 수도 있습니다. r 이외의 옵션을 선택하면 변수를 1로 변경하는 줄이 있습니다. 명령문을 완성한 후 "변수가 0이면 기본 명령을 실행합니다"라고 쓸 수 있습니다.


나는 Cas의 답변이 가장 좋다고 생각합니다. 댓글을 달고 싶지만 권한이 없습니다. 나는 그의 아이디어를 기반으로 할 것입니다. 이는 Cas가 제안한 것과 동일하지만 명령이 하나만 있고(그래서 동일한 명령이 두 개가 있어서 나중에 실수하는 일이 없음) -H 외에 추가로 사용할 수 있는 가능성을 제공합니다.

DEF="Default command executed"
while getopts ":hr" opt;
   do case $opt in 
     h) show_help; 
        exit 1 ;; 
     r) echo "$DEF" ;; 
     *) echo "$DEF" ;; 
  esac
done

관련 정보