arguments - Getopt not parsing well bash -
i wrote script in bash serving template several monitors. choose getopt in order able use long options on cli. however, have problems implementing correctly.
the whole script lot longer, relevant part:
#!/bin/bash # # function # main # description # main function. called here # args # nothing # # return code # nothing # # main function. called here main() { # parse options , arguments parse_options "${@}" # check if interval set valid number check_interval } # # function # check_interval # description # checks if number valid # args # 1: number checked # return code # 0: valid # 1: invalid # check_interval() { # don't have worry if interval set @ all, because getopt doing if ( ! check_number_pos ${arginterval} ); echo "error: invalid interval: ${arginterval}" show_usage exit 2 fi } # # function # show_usage # description # usage section. showing usage according docopt standards # args # nothing # return code # nothing # show_usage() { echo "usage:" >&2 echo " ${this_script_name} -i|--interval=<interval in s> [-r | --random [--randomwait=<wait in s>]] [-v|--verbose] [-d|--debug] [--colors]" >&2 echo " ${this_script_name} [-h|--help]" >&2 } # # function # check_number_pos # description # checks if number valid , positive # args # 1: number checked # # return code # 0: valid , positive # 1: invalid or negative # check_number_pos() { local returnval if [[ "${1}" =~ ^[0-9]+$ ]]; returnval=0 else returnval=1 fi return ${returnval} } # # function # parse_options # description # parse options command line # args # @: arguments , options given @ cli # return code # nothing # parse_options() { # use getopt(1) parse options according posix. if fails, error shown, , we're showing usage , exit # add new options here , in case-statement below. # short options must added in 'options'-section # long options must added in 'longoptions'-section # short options must have long equivalent # --name set error-output not show 'getopt'-errors neat <application name>-errors # options , longoptions have following format: # <letter> option without argument # <letter>: option mandarory argument # <letter>:: option optional argument <- broken short options , long options without '='. don't use it! local -r getopt=$(getopt --name ${0} --options hrvdi: --longoptions help,random,verbose,debug,colors,randomwait:,interval: -- "${@}") if [ ${?} != 0 ]; echo "error: error while getting arguments" show_usage exit 127; fi # no options or arguments given. show usage. if [[ "${getopt}" == " --" ]]; show_usage exit 127; fi # evaluate getopt. need have quotes in output of getopt(1) interpreted. eval set -- "${getopt}" # walk through options. don't put code in here, point function or set variable. # please note, new options need added here in getopt line above. # note: shift removes first value string, option removed getopt-string, , argument available in $1 # after using argument, please shift again, next option first value in getopt while true; case "${1}" in -i|--interval) shift arginterval=${1} shift ;; -r|--random) shift flagrandom=1 ;; --randomwait) shift flagrandom=1 argrandom=${1} shift ;; -v|-d|--verbose|--debug) flagdebug=1 shift ;; --colors) flagcolors=1 shift ;; -h|--help) #show_help exit 0 ;; --) shift break ;; -*) echo "error: unrecognized option ${1}" show_usage exit 127 ;; *) show_usage exit 127 ;; esac done } #call main function after main "${@}"
now, when call script right way, goes smooth:
$ ./test1.sh -i 10
when forget argument, want:
$ ./test1.sh -i ./test1.sh: option requires argument -- 'i' usage: -i|--interval=<interval in s> [-r | --random [--randomwait=<wait in s>]] [-v|--verbose] [-d|--debug] [--colors] [-h|--help]
but when forget argument , add one, fails:
$ ./test1.sh -i --colors error: invalid interval: --colors usage: -i|--interval=<interval in s> [-r | --random [--randomwait=<wait in s>]] [-v|--verbose] [-d|--debug] [--colors] [-h|--help]
this happens because check if interval integer, other purposes, dangerous thing how can change case not read options arguments? far getopt not serving me well, because ran bug/feature well: 'optional argument' (::) not working expected works when used '=' between option , argument.
versions:
$ getopt -v getopt (enhanced) 1.1.4 $ bash --version gnu bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
getopt
doesn't know semantics of options. knows, --colors
valid argument -i
option. have check these kinds of errors yourself, unfortunately, if want handle them.
while true; case "${1}" in -i|--interval) shift arginterval=${1} if [[ $arginterval = -* ]]; printf 'you appear have forgotten interval argument before %s option\n' "$arginterval" >&2 exit 1 fi shift ;; ...
Comments
Post a Comment