4
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Bashでgetopts使って引数を解析する

Last updated at Posted at 2019-01-03

はじめに

getopts でできることをまとめておく。
ロングオプションはできないと書かれた記事があるけれど、できたよ。

こんなことができたら素敵

$ ./a.sh -h
usage: ./a.sh [OPTIONS...] ARGS...

options:
 -v, --verbose
 -h, --help
$ ./a.sh
option_verbose: 0
$ ./a.sh --verbose
option_verbose: 1

コードサンプル1

# !/bin/bash

set -eu

usage_exit() {
  prog="./$(basename $0)"
  echo_err "usage: $prog [OPTIONS...] ARGS..."
  echo_err ""
  echo_err "options:"
  echo_err " -v, --verbose"
  echo_err " -h, --help"
  exit 1
}

echo_err() {
  echo "$1" 1>&2
}

echo_err_badopt() {
  local optarg="$1"
  echo_err "$0: illegal option -- $optarg"
}

option_verbose=0

while getopts -- "-:hv" OPT; do
  case $OPT in
    -)
      case $OPTARG in
        help) usage_exit;;
        verbose) option_verbose=$(($option_verbose+1));;
        *) echo_err_badopt $OPTARG; usage_exit;;
      esac;;
    h) usage_exit;;
    v) option_verbose=$(($option_verbose+1));;
    \?) usage_exit;;
  esac
done
shift $((OPTIND-1))

if [[ $# -ne 0 ]]; then
    usage_exit
fi

echo "option_verbose: $option_verbose"
exit 0

コードサンプル2

先ほどのサンプルではもの足りない方はこちらを参照:

# !/bin/bash

set -eu

usage_exit() {
  prog="./$(basename $0)"
  echo_err "usage: $prog [OPTIONS...] ARGS..."
  echo_err ""
  echo_err "options:"
  echo_err " --dry-run           : Don't make any change (default)"
  echo_err " -f, --force         : Force mode"
  echo_err " -l ITEM --list ITEM : Set list items"
  echo_err " -V VAL --value VAL  : Set value"
  echo_err " -v, --verbose       : Verbose mode"
  exit 1
}

echo_err() {
  echo "$1" 1>&2
}

echo_err_needarg() {
  local optarg="$1"
  echo_err "$0: option requires an argument -- $optarg"
}

echo_err_badopt() {
  local optarg="$1"
  echo_err "$0: illegal option -- $optarg"
}

option_dry_run=yes
option_list=()
option_value=''
option_verbose=0

while getopts -- "-:fhl:V:v" OPT; do
  case $OPT in
    -)
      case $OPTARG in
        dry-run)
          option_dry_run=yes
          ;;
        force)
          option_dry_run=no
          ;;
        list)
          if [[ $OPTIND -gt $BASH_ARGC ]]; then
            echo_err_needarg $OPTARG
            usage_exit
          fi
          LONGOPT_ARG="${BASH_ARGV[$(($BASH_ARGC-$OPTIND))]}"
          option_list+=($LONGOPT_ARG)
          OPTIND=$((OPTIND+1))
          ;;
        value)
          if [[ $OPTIND -gt $BASH_ARGC ]]; then
            echo_err_needarg $OPTARG
            usage_exit
          fi
          LONGOPT_ARG="${BASH_ARGV[$(($BASH_ARGC-$OPTIND))]}"
          option_value=$LONGOPT_ARG
          OPTIND=$((OPTIND+1))
          ;;
        verbose)
          option_verbose=$(($option_verbose+1))
          ;;
        *)
          echo_err_badopt $OPTARG
          usage_exit
          ;;
      esac;;
    f) option_dry_run=no;;
    h) usage_exit;;
    l) option_list+=($OPTARG);;
    V) option_value=$OPTARG;;
    v) option_verbose=$(($option_verbose+1));;
    \?) usage_exit;;
  esac
done
shift $((OPTIND-1))

cat <<__JSON__
{
  "option_dry_run": "$option_dry_run",
  "option_value": "$option_value",
  "option_verbose": $option_verbose,
  "option_list": [$(
    if [[ ${#option_list[@]} -ne 0 ]]; then
      for e in ${option_list[@]}; do
        echo "\"$e\""
      done | paste -sd,
    fi
  )],
  "arguments": [$(
    i=0
    while [[ $# -gt 0 ]]; do
      echo "\"$1\""
      shift
    done | paste -sd,
  )]
}
__JSON__

その他

正直、動くけどロングオプションで引数は受けたくない。
bashでやれなくないけどやるの?、って感じ。

参考資料

4
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?