3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

シェルスクリプトの簡素なオプション引数解析

3
Last updated at Posted at 2019-04-13

こんにちは。
シェルスクリプトの自力による引数処理(解析)を作りました1arg_parse.sh)。テンプレートとして利用できると思います。

特徴

  • ショートオプション名、ロングオプション名、複合フラグ2、引数付きオプションへ対処します。
  • 誤った使い方を検出し安全に停止します。
  • オプション引数解析部コード(whileループ)の簡素化、およびUSAGE/Options(= helpメッセージ)内容と良好に対応するよう努めました。
  • POSIX 準拠シェルで動きます。

制約条件

  • オプション(およびその引数)は前半へ、位置引数(主引数)は後半へ固まっている必要があります。
  • ''"" を引数付きオプションの引数として与えるには、空白区切り型(例:-m "")で指定する必要があります(シェルに認識させるためです)。
  • - で始まる文字列を引数付きオプションの引数として与えるには、密着型(例:-m"-xyz")で指定する必要があります。
  • - で始まる文字列を位置引数として与えるには、位置引数の始まりを明示した後(--)、それ以降に指定する必要があります(例:./arg_parse.sh -- -1 -2)。

動作例

DEBUG モード

$ dash arg_parse.sh -mdog -l9 1 2 3
$ dash arg_parse.sh -m dog -l 9 1 2 3
optional arguments:
 -m: dog
 -l: 9
positional arguments: 1 2 3
ロングオプション名で動かした例
$ dash arg_parse.sh --mammal cat --loops 9 I II III
$ dash arg_parse.sh --mammal=cat --loops=9 I II III
optional arguments:
 -m: cat
 -l: 9
positional arguments: I II III

誤った使い方の検出例

$ dash arg_parse.sh --loops -xy
Warning: Type "arg_parse.sh --help" for usage instructions.
- Option '--loops' requires an argument
- Unknown option: '-x'
- Unknown option: '-y'

help オプションでの動作例

$ dash arg_parse.sh --help

    Name: arg_parse.sh - parse arguments

    Usage: arg_parse.sh [options] [positinal_argument [...]]

    Options:
      -h|--help          Show this usage and exit.
      -d|--debug         Enable debug mode.
      -l|--loops N       Set the number of loops (default: 1)
      -m|--mammal NAME   Set mammal name.

Source code

説明

  • while ループは、位置パラメータを shift しながら、オプション引数を先頭順に取り出します。

  • extract_opt_value_f(内部関数)は、 引数つきオプション(+引数)から、その引数部分を取り出します(動作例では -m|--mammal などの直後の値)。

    • 加えてwhileループで使うための shift 数を求めます。
  • 他の部分はエラー処理・メッセージ出力などのためのコードです。

解析部コードを機械的に生成

USAGE/Options(helpメッセージ)の記述は、オプション引数解析部(whileループ)のコードと対応させており、率直に解析部コードを記述できています。

さらにはその記述から機械的にコードを生成できそうで、やってみました。例えば、

-h|--help 
-d|--debug  
-l|--loops N 
-m|--mammal NAME 

を与えると下記が生成されます3

while [ $# -gt 0 ]; do
  opt_token="$1"
  case "$opt_token" in
    -h|--help)      help_enabled=$TRUE;;
    -d|--debug)     debug_enabled=$TRUE;;
    -l*|--loops*)   n_loops_var=$(extract_opt_value_f -l--loops "$@");;
    -m*|--mammal*)  name_mammal_var=$(extract_opt_value_f -m--mammal "$@");;
    -[!-][!-]*)     split_combined_option_global_f "$opt_token"; shift
                    set -- "$first_flag" "$rest_flags" "$@"; continue;;
    --)             shift; break;;
    -*)             append_warning_f "Unknown option: '$opt_token'";;
    *)              break;;
  esac
  shift_additional=$?
  if [ $shift_additional -lt $EXTRACT_FAILED ]; then
    shift $shift_additional  # 0: default, 1: next arg by extract_opt_value_f
  else
    append_warning_f "Option '${opt_token%=}' requires an argument"
  fi
  shift
done
  1. 場合によっては自力ではなく、getopt, getopts, docopts の利用も良いでしょう。

  2. 例えば ls -l -tls -lt と表すものです。

  3. ただし変数名を機械的に作っているのでぎこちないです。

3
1
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
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?