sonumb

bash 스크립트에서 긴 옵션 처리하기 - getopt(1) 예제 본문

개발자 이야기

bash 스크립트에서 긴 옵션 처리하기 - getopt(1) 예제

sonumb 2021. 11. 26. 12:57

개요

배시 스크립트에서 builtin 명령어인 "getopts" 를 사용해서 실행 옵션을 처리할 수 있다.
https://systemdesigner.tistory.com/17

 

쉘 스크립트의 인자를 보다 세련되게 (getopt)

쉘 스크립트를 사용하다 보면 사용자 입력을 받아야 되는 경우가 많습니다. 그 때 보다 세련되고 있어??? 보이게 끔 받을 수 있는 방법을 소개하고자 합니다. getopt라는 명령어 인데 먼저 ... 샘플

systemdesigner.tistory.com

 

그러나, "--special-example=true"와 같은 긴 옵션은 처리하지 못한다.

 

getopts 말고  getopt(1) 명령어를 이용해서 처리한다.
https://man7.org/linux/man-pages/man1/getopt.1.html

 

getopt(1) - Linux manual page

getopt(1) — Linux manual page GETOPT(1) User Commands GETOPT(1) NAME         top getopt - parse command options (enhanced) SYNOPSIS         top getopt optstring parameters getopt [options] [--] optstring parameters getopt [options] -o|--options o

man7.org

 

예제는 아래 링크를 참조해서 좀 더 다듬어 보았다.
https://bl.ocks.org/magnetikonline/22c1eb412daa350eeceee76c97519da8

 

Bash getopt long options with values usage example.

Peter Mescalchin’s Block 22c1eb412daa350eeceee76c97519da8

bl.ocks.org

예제 소스

#!/bin/bash

###################################################
# 인자값이 필요한 옵션 및 설명
###################################################
OPTS_WITH_VAL=(
    "opt-one"
    "opt-two"
    "opt-three"
)

OPTS_WITH_VAL_DESC=(
    "description of opt-one"
    "description of opt-two"
    "description of opt-three"
)

###################################################
# 값이 필요없는 옵션 및 설명
###################################################
OPTS_NO_VAL=(
    "opt-only1"
    "opt-only2"
    "opt-only3"
    "help"
)

OPTS_NO_VAL_DESC=(
    "description of opt-only1"
    "description of opt-only2"
    "description opt-only3"
    "print usage"
)

###################################################
# 사용 방법 출력
###################################################
function print_usage() {
  pg_name=`basename $0`
  _opts_list_with_val=$(printf "[--%s=<val>] " "${OPTS_WITH_VAL[@]}")
  _opts_list_no_val=$(printf "[--%s] " "${OPTS_NO_VAL[@]}")

  echo ""
  echo "USAGE:"
  echo "  $pg_name ${_opts_list_with_val}"
  echo "        ${_opts_list_no_val}"

  echo ""
  echo "DESCRIPTIONS:"
  # 값을 필요로 하는 옵션들의 설명 출력
  for (( i=0 ; i<${#OPTS_WITH_VAL[@]} ; i++)) ;
  do
    printf "    --%s=<val>,\t%s\n" ${OPTS_WITH_VAL[$i]} "${OPTS_WITH_VAL_DESC[$i]}"
  done
  # 값이 필요없는 옵션 설명 출력
  for (( i=0 ; i<${#OPTS_NO_VAL[@]} ; i++)) ;
  do
    printf "    --%s,\t%s\n" ${OPTS_NO_VAL[$i]} "${OPTS_NO_VAL_DESC[$i]}"
  done
}

###################################################
# 옵션 개수 검사
###################################################
if [[ $# -lt 1 ]]; then
  echo "ERROR: need args"
  print_usage
  exit
fi

###################################################
# 처리할 옵션 포매팅 및 세팅
###################################################
_opts_list_with_val=$(printf "%s:," "${OPTS_WITH_VAL[@]}")
_opts_list_no_val=$(printf "%s," "${OPTS_NO_VAL[@]}")
opts_list_str=${_opts_list_with_val}${_opts_list_no_val}

# read arguments
opts=$(getopt \
    --longoptions $opts_list_str \
    --name "$(basename "$0")" \
    --options "h?" \
    -- "$@"
)

if [[ $? -ne 0 ]]; then
  print_usage
  exit 1
fi

eval set --$opts

###################################################
# 옵션들 처리하기
###################################################
while [[ $# -gt 0 ]]; do
  value=""
  case "$1" in
    "--"${OPTS_WITH_VAL[0]})
      value=$2
      shift 2
      ;;

    "--"${OPTS_WITH_VAL[1]})
      value=$2
      shift 2
      ;;

    "--"${OPTS_WITH_VAL[2]})
      value=$2
      shift 2
      ;;

    "--"${OPTS_NO_VAL[0]})
      echo ${1#--} is on
      shift 1
      ;;

    "--"${OPTS_NO_VAL[1]})
      echo ${1#--} is on
      shift 1
      ;;

    "--"${OPTS_NO_VAL[2]})
      echo ${1#--} is on
      shift 1
      ;;

    "h"|"?"|"--"${OPTS_NO_VAL[3]})  # --help
      print_usage
      exit 0
      ;;

    "--")
      echo "-- End of options --"
      break;
      ;;
      
    *)
      print_usage
      exit 1
      ;;
  esac

  if [[ ! -z $value ]]; then
    echo $value
  fi
done

실행 결과

"인자 값 없을 경우"와 --help, -h 옵션인 경우 사용법 출력

$ sh parse_longopt.sh
ERROR: need args

USAGE:
  parse_longopt.sh [--opt-one=<val>] [--opt-two=<val>] [--opt-three=<val>]
        [--opt-only1] [--opt-only2] [--opt-only3] [--help]

DESCRIPTIONS:
    --opt-one=<val>,    description of opt-one
    --opt-two=<val>,    description of opt-two
    --opt-three=<val>,    description of opt-three
    --opt-only1,    description of opt-only1
    --opt-only2,    description of opt-only2
    --opt-only3,    description opt-only3
    --help,    print usage

$ sh parse_longopt.sh -h

USAGE:
  parse_longopt.sh [--opt-one=<val>] [--opt-two=<val>] [--opt-three=<val>]
        [--opt-only1] [--opt-only2] [--opt-only3] [--help]

DESCRIPTIONS:
    --opt-one=<val>,    description of opt-one
    --opt-two=<val>,    description of opt-two
    --opt-three=<val>,    description of opt-three
    --opt-only1,    description of opt-only1
    --opt-only2,    description of opt-only2
    --opt-only3,    description opt-only3
    --help,    print usage

$ sh parse_longopt.sh --help

USAGE:
  parse_longopt.sh [--opt-one=<val>] [--opt-two=<val>] [--opt-three=<val>]
        [--opt-only1] [--opt-only2] [--opt-only3] [--help]

DESCRIPTIONS:
    --opt-one=<val>,    description of opt-one
    --opt-two=<val>,    description of opt-two
    --opt-three=<val>,    description of opt-three
    --opt-only1,    description of opt-only1
    --opt-only2,    description of opt-only2
    --opt-only3,    description opt-only3
    --help,    print usage

인식할 수 없는 옵션을 주었을 경우.

$ sh parse_longopt.sh --wrong-opt
parse_longopt.sh: 인식할 수 없는 옵션 '--wrong-opt'

USAGE:
  parse_longopt.sh [--opt-one=<val>] [--opt-two=<val>] [--opt-three=<val>]
        [--opt-only1] [--opt-only2] [--opt-only3] [--help]

DESCRIPTIONS:
    --opt-one=<val>,    description of opt-one
    --opt-two=<val>,    description of opt-two
    --opt-three=<val>,    description of opt-three
    --opt-only1,    description of opt-only1
    --opt-only2,    description of opt-only2
    --opt-only3,    description opt-only3
    --help,    print usage

정상적인 옵션인 경우.
(✅--opt-three 'three' 와 같이 '='가 없더라도 정상적으로 처리한다)

$ sh parse_longopt.sh --opt-one='abc' --opt-two="two" --opt-three 'three' --opt-only1 --opt-only2
abc
two
three
opt-only1 is on
opt-only2 is on
-- End of options --

$
반응형