#!/bin/sh # platform ... devuan dash # GPL_3+ cat << 'EEE' > /dev/null /* rdopt ....read option, simple option parse helper. bourne-shell script. * Copyright (C) 2017 Momi-g * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ EEE # usage-------- if [ "$#" -eq 0 ] || [ "$1" = '-h' ] ; then cat << 'EEE' HowTo (readopt, option parse helper. bourne-shell script.) option: -h (this) ------ eg.) ~$ rdopt ":ab:cd:" zzz -b vvv "y' y" -a # format first ':' is quiet err. >> OPTIND=1 ; opt_a='1' opt_b='vvv' (subarg type is defined only when selected. ck ${opt_d+aaa}) opt_c='' (switch type opt is always declared. 'set -u' etc.) set -- 'zzz' 'y'"'"' yy' (literal safe) eg.) #!/bin/sh # run... yoursh.sh zzz -b vvv -c yyy buf=`rdopt ":ab:cd:" "$@"` #use "$@" or $@, not work at $* eval "$buf" if [ $? -ne 0 ] ; then echo "optErr. $OPTARG" >/dev/stderr ; exit 1; fi if [ "${opt_d+bb}" = "" ] ; then echo "no -d opt" ; fi #(man:param expantion) echo "$opt_b $@ $#" # >>> vvv, zzz yyy, 2 ...opts removed - check all args or until detect '--'. yoursh.sh -c zzz -5+4 >> NG. -5 is treated as option. rtns err. yoursh.sh -c zzz -- -5+4 >> OK. -5+4 parsed as args '$1' - if failed to parse option, ' eval "$buf" ' returns $?=1 wrong optchar is set to OPTARG (OPTARG='z' etc) - if not quiet mode (:a:bc -> a:bc etc), disp errmsg & sleep loop. - you can use parse function directly (copy & paste). see source. EEE exit 0 fi # purse func. # maybe you can copy & paste to your script directly. # time # normal use: 10-20 ms # copy&paste: 5-10 ms ########## copy start ########### func_rdopt() { ( # subshell. local vars. rdopt_fmt="$1" # ":ab:c" etc. format. shift #ck quiet mode rdopt_quiet=1 rdopt_buf=${rdopt_fmt%%[!:]*} if [ "$rdopt_buf" != ':' ] ; then rdopt_quiet=0 rdopt_fmt=':'"$rdopt_fmt" fi #--inicialize make list opt_a='', ... #ab:c -> 'a' \n 'c' \n ... omit 'b:' ... for check null pointer or "blank" rdopt_buf='s/.://g s/://g s/./&\ /g' rdopt_zerolist=`echo "$rdopt_fmt" | sed -e "$rdopt_buf" | sed -e " /^$/d s/^/opt_/g s/$/=''/g " ` #--- local vars # rdopt_fmt="$1" # ":ab:c" opt format # rdopt_quiet=1 # rdopt_zerolist=`echo "$rdopt_fmt" | sed -e "$rdopt_buf" | sed -e " # rdopt_buf='s/://g rdopt_out="" rdopt_opt="" rdopt_skip="" rdopt_err="" rdopt_safe=" s#'#'\"'\"'#g 1 s/^/'/g $ s/$/'/g" #---getopts loop. break if all args read or detect '--' while : do if [ 0 -eq "$#" ] || [ "$rdopt_err" = "1" ] ; then break fi if [ "$1" = "--" ] ; then shift ; break fi getopts "$rdopt_fmt" rdopt_opt "$@" # ":a:bc:f:" etc... # err detect@silent mode # $?=1 ... detect optend or '--'. '--' is removed at previous line. # ':' ... detect option, but dont have subargs (OPTARG="factor"). # '?' ... detect unsupported option char (OPTARG="factor") or args end (OPTARG="blank"). # OPTARG ... if err, "" is optend. "a/b/c..." is invalid option # OPTIND ... if err, OPTIND indicates next (new) arg pos. if [ "$?" = "1" ] ; then # normal end (detect normal args). save general args. shift $((OPTIND - 1)) if [ "$#" -eq "0" ] ; then break fi # new set make rdopt_buf=`printf '%s\n' "$1" | sed -e "$rdopt_safe"` rdopt_skip="$rdopt_skip $rdopt_buf" shift OPTIND=1 continue fi if [ "$rdopt_opt" = "?" ] || [ "$rdopt_opt" = ":" ] ; then # detect invalid opt rdopt_err=1 #OPTARG has err option char. continue fi # though err filter. below is for normal. detect option. #if [ "$OPTARG" = "" ] ; then # no subargs >>> debag. fixed. # 2とは限らない。 -f 123 -f123 が同じ。-fh で-f -hもありえるし-f""と -g -h # OPTARGだけでは分からない。フォーマットを見ないと。f:を探すしかない。 # optchar has ':' or not buf=${rdopt_fmt#*$rdopt_opt} #fmt ... :a:bc:d ... buf=${buf%%[!:]*} if [ "$buf" != ":" ] ; then # no subargs rdopt_out="$rdopt_out opt_$rdopt_opt"'=1' else # exist subargs. =2 rdopt_buf=`printf "%s\n" "$OPTARG" | sed -e "$rdopt_safe" ` rdopt_out="$rdopt_out opt_$rdopt_opt"'='"$rdopt_buf" fi done # exit parse if [ "$rdopt_err" = "1" ] ; then if [ "$rdopt_quiet" = "0" ] ; then rdopt_buf=${0##*/} echo "$rdopt_buf: invalid option. sleep. ( $OPTARG )" >/dev/stderr while : do sleep 1000 done exit 1 else rdopt_out="OPTARG=$OPTARG OPTIND=1 test 1 = 0" fi else # if '--' end ... if [ "$#" != "0" ] ; then rdopt_buf="" for ii do rdopt_buf="$rdopt_buf "`printf '%s\n' "$ii" | sed -e "$rdopt_safe" ` done rdopt_skip="$rdopt_skip $rdopt_buf" fi # output rdopt_out="OPTIND=1 $rdopt_zerolist $rdopt_out set -- $rdopt_skip" fi printf '%s\n' "$rdopt_out" ) } ########## copy end ########### # direct use sample # buf=`func_rdopt ':ab:c:d' "$@" ` # eval "$buf" # if [ $? != 0 ] ; then echo "err. $OPTARG" >/dev/stderr ; exit 1; fi # ... or ... # buf=`func_rdopt 'ab:c:d' "$@" ` # stop mode. # ---main func_rdopt "$@"