getopt1.sh (3910B)
1 #!/bin/bash 2 # -*- coding:utf-8 -*- 3 4 # Usage 5 # 6 # local "${_ble_getopt_vars[@]/%/=}" # WA #D1570 checked 7 # ble-getopt-begin "progname" "m:n c:n,n k:n,n" "$@" 8 # ble-getopt 9 # 10 # ToDo 11 # 12 # * next-argument: appropriate error message 13 # * next-argument: negative tests 14 # * next-argument: function calls 15 # * getopt_index を OPTIND に名前を変える? 16 17 _ble_getopt_vars=( 18 optargs # 読み取られたオプション 19 20 getopt_cmd # 呼出元コマンド名 21 getopt_odefs # オプション定義 22 getopt_args # コマンド引数 23 getopt_len # コマンド引数の数 24 getopt_index # 現在のコマンド引数の位置 OPTIND 25 26 getopt_opt # 解析中オプション 27 getopt_oarg # オプション引数 28 getopt_olen # オプション引数の数 29 getopt_oind # オプション引数の現在位置 30 ) 31 32 function .ble-getopt.next-argument { 33 local type=$1 oarg 34 if ((getopt_oind<getopt_olen)); then 35 oarg=${getopt_oarg[getopt_oind++]} 36 elif ((getopt_index<getopt_len)); then 37 oarg=${getopt_args[getopt_index++]} 38 else 39 if [[ $type == '?'* ]]; then 40 oarg=${type:1} 41 [[ ! $oarg ]] && return 0 42 else 43 ble/util/print "$getopt_cmd: missing an argument of the option \`${optargs[0]}'." 1>&2 44 return 1 45 fi 46 fi 47 48 # check 49 case $type in 50 [nefdhcbpugkrwxsv]) 51 if [ ! -$type "$oarg" ]; then 52 ble/util/print "$getopt_cmd: the argument of the option \`${optargs[0]}' is empty string (oarg=$oarg)." 1>&2 53 return 1 54 fi ;; 55 esac 56 57 optargs[${#optargs[@]}]=$oarg 58 } 59 60 function .ble-getopt.process-option { 61 local name=$1 62 optargs=("$name") 63 64 # search the option definition 65 local i f_found adef 66 for ((i=0;i<${#getopt_odefs[@]};i++)); do 67 if [[ $name == "${getopt_odefs[$i]%%:*}" ]]; then 68 f_found=1 69 ble/string#split adef : "${getopt_odefs[i]}" 70 break 71 fi 72 done 73 74 # unknown option 75 if [[ ! $f_found ]]; then 76 if [[ $f_longname ]]; then 77 ble/util/print "an unknown long-name option \`--$name'" 1>&2 78 else 79 ble/util/print "an unknown option \`-$name'" 1>&2 80 fi 81 return 1 82 fi 83 84 for ((i=1;i<${#adef[@]};i++)); do 85 .ble-getopt.next-argument "${adef[$i]}" || return 1 86 done 87 } 88 89 function ble-getopt-begin { 90 ble/string#split-words getopt_cmd "$1" 91 ble/string#split-words getopt_odefs "$2" 92 shift 2 93 getopt_args=("$@") 94 getopt_len=${#getopt_args[@]} 95 getopt_index=0 96 97 getopt_opt= 98 getopt_olen=0 99 getopt_oind=0 100 101 optargs=() 102 } 103 104 function .ble-getopt.check-oarg-processed { 105 if ((getopt_oind<getopt_olen)); then 106 ble/util/print "$getopt_cmd: an option argument not processed (oarg=${getopt_oarg[$getopt_oind]})." 1>&2 107 getopt_oind=0 108 getopt_olen=0 109 builtin unset -v 'getopt_oarg[@]' 110 return 1 111 fi 112 } 113 114 function ble-getopt { 115 # 読み掛けのオプション列 116 if [[ $getopt_opt ]]; then 117 local o=${getopt_opt::1} 118 getopt_opt=${getopt_opt:1} 119 .ble-getopt.process-option "$o" 120 return "$?" 121 fi 122 123 # oarg が残っていたらエラー 124 .ble-getopt.check-oarg-processed || return 1 125 126 # 完了 127 if ((getopt_index>=getopt_len)); then 128 builtin unset -v 'optargs[@]' 129 return 2 130 fi 131 132 local arg=${getopt_args[getopt_index++]} 133 if [[ $arg == -?* ]]; then 134 135 if [[ $arg == --?* ]]; then 136 # longname option 137 local f_longname=1 138 getopt_opt=${arg:2} 139 140 local o=${getopt_opt%%=*} 141 if [[ $o != "$getopt_opt" ]]; then 142 getopt_oarg=("${getopt_opt#*=}") 143 getopt_oind=0 144 getopt_olen=1 145 fi 146 getopt_opt= 147 148 .ble-getopt.process-option "$o" 149 .ble-getopt.check-oarg-processed || return 1 150 return 0 151 else 152 # short options 153 local f_longname= 154 getopt_opt=${arg:1} 155 156 ble/string#split getopt_oarg : "$getopt_opt" 157 getopt_olen=${#getopt_oarg[@]} 158 getopt_oind=1 159 ble-getopt 160 return "$?" 161 fi 162 else 163 # 通常の引数 164 optargs=('' "$arg") 165 fi 166 167 }