Parsing arguments to bash functions

In bash one can parse arguments with either getopt (allowing longopts) or with the simpler getopt (very basic). There is also the option of parsing things yourself. I am gravitating towards parsing them myself.

Hello,

Speaking purely in terms of my own personal experience and preferences, I've tended to go with parsing my own arguments in shell script functions. Things like getopt always just seemed like overkill for me, and a lot of work for what ultimately came across as not very much gain, at least not in the situations I was writing scripts in.

If you're writing a shell script that is going to be used by users other than yourself, and which will be expected by those users to take traditional double-dash GNU-style command line arguments (and which in turn is written internally in such a way as to pass those command-line arguments straight into functions), then I can see the appeal, perhaps. But in situations where you're writing your own script for your own use, and where you will always know what arguments a given function will need and in which this argument passing only ever takes place internally within the script, you might as well just read the positional arguments directly, I'd say.

Of course, different situations call for different solutions, and for what you're doing, you might find that getopt is in fact less work than (for example) ending up writing your own argument parser, if your script is sufficiently complex to need such a thing. But if all you need to do is pass a few single arguments into a function so it can perform a task within your script, then getopt is probably just creating more work for yourself than you'd need, when you could just use the default positional argument variables.

I like to handle myself, not using getopt.

Here is my core solution to handle options and arguments without getopt. Works using any posix compatible shell like ksh, bash, zsh, dash, ...

Example not include error handling if option need argument, but caller has not given it.

# example  cmd -o val -s val2  -k -l  -- -arg1 arg2 arg3
#  -arg1 is argument, not option
# example  cmd --option val --setup val2  -k --log  -- -arg1 arg2 arg3
# example  cmd -o val -s val2  -k -l  arg2 arg3

##########
usage()
{
        echo "usage ...." >&2
}

##########
err()
{
        echo "$*" >&2
}

########## MAIN
# set defaults as you need
oval="0"
sval=""   # mandatory, caller have to give value
kflag=0  # or use builtin true/false
lflag=0

# loop options, not arguments
while [ $# -gt 0 ]
do
        arg="$1"
        case "$arg" in
                -o|--option) oval="$2" ; shift ;;  # read option with value
                -s|--setup) sval="$2" ; shift ;;  # read option with value
                -k) kflag=1 ;;            # set flag true
                -l|--log) lflag=1 ;;      # set flag true
                --) shift; break ;;       # -- options end, next values are arguments
                -*) usage ; exit 1 ;;     # unknown option
                *) break ;;               # arguments
        esac
        shift
done

# check mandatory values
[ "$sval" = "" ] && usage && err "need -s value" && exit 2

# now $* / $@ include argument values

# testing
echo "sval $sval - oval $oval - lflag $lflag - kflag $kflag"
echo "arguments $*"

How can I handle an option with an optional argument ?

I have never done options which has optional argument. When you creating your script, you can make rules for options and arguments. Yes, I'm little lazy, but I can't see why I need to offer option with optional argument(s).