Shellscript コマンドライン引数のパース(Bash)
Shellscript でコマンドライン引数をパースしたい。※注意: fish は勿論 sh は実行不可で bash のみ動作します
変数のスコープ
前提として変数のスコープを理解しておく。
#!/bin/bash func-echo() { echo "$VarA" local VarB="Variable B" VarC="Variable C" } func-main() { local VarA="" func-echo # 空文字 VarA="Variable A" func-echo # Variable A func-echo 内から変数 VarA を呼び出すことができる echo "$VarB" # 空文字 func-echo 内のローカル変数にはアクセス不可 echo "$VarC" # Variable C func-echo 内のグローバル変数にはアクセス可能 } func-main
shift の使い方
shift
で引数(配列)の先頭を削除する。$#
は長さ(length)
#!/bin/bash set foo bar baz func-main() { echo "$@" # foo bar baz echo "$1" # foo echo "$2" # bar echo "$3" # baz echo "$1" # foo echo "$#" # 3 shift echo "$1" # bar echo "$#" # 2 shift echo "$1" # baz echo "$#" # 1 } func-main "$@"
引数をパースするコード
#!/bin/bash func-usage() { cat <<EOS Usage: $NAME [options] [arguments] Options: -h, --help Display this help and exit. -v, --version Output version information and exit. -n, --no-required Arguments no required. -r, --required Arguments required. -o, --optional Argument is optional. EOS exit 2 } func-version() { echo "$NAME: $VERSION" exit 2 } func-error() { echo "Error: $1." 1>&2 exit 1 } func-parse() { local skip=0 # 値を必要としないオプション opt_no_required=false # 値が必須なオプション opt_required=false # 値が任意なオプション opt_optional=false # $@ の長さが 0 になるまでループする while (($# > 0)); do case "$1" in -n | --no-required) # 値を必要としないオプション opt_no_required=true skip=1 ;; -r | --required) # 値が必須なオプション # 値が無いまたは - から始まる値はエラーにする if [[ -z "$2" ]] || [[ "$2" =~ ^-+ ]]; then func-error "'$1' options require arguments"; fi opt_required="$2" skip=2 ;; -o | --optional) # 値が任意なオプション opt_optional=true skip=1 # 値があるか - で始まらない場合は値をセットする if [[ -n "$2" ]] && [[ ! "$2" =~ ^-+ ]]; then opt_optional="$2" skip=2 fi ;; -v | --version) func-version ;; -*) func-usage ;; esac case "$skip" in 1) # 変数 skip が 1 の場合は値がないオプション skip=0 shift ;; 2) # 変数 skip が 2 の場合は値を指定したオプション skip=0 shift 2 ;; *) # 変数 skip が 0 の場合は残りの引数として配列 remain に入れておく remain+=("$1") shift ;; esac done } func-main() { local NAME="command" local VERSION="v0.1" local -a remain=() func-parse "$@" echo "required : $opt_required" echo "no required: $opt_no_required" echo "optional : $opt_optional" echo "remain args: ${remain[*]}" } func-main "$@"
実行結果
$ ./command.sh -n foo -r bar baz -o required : bar no required: true optional : true remain args: foo baz
$ ./command.sh --version command: v0.1
$ ./command.sh --help Usage: command [options] [arguments] Options: -h, --help Display this help and exit. -v, --version Output version information and exit. -n, --no-required Arguments no required. -r, --required Arguments required. -o, --optional Argument is optional.