'getopts & preventing accidentally interpreting short options as arguments

Here's a toy example that shows what I mean:

while getopts "sf:e:" opt; foundOpts="${foundOpts}${opt}" ; done
echo $foundOpts

problem is that getopts isn't particularly smart when it comes to arguments. for example, ./myscript.sh -ssssf will output option requires an argument -- f. That's good.

But if someone does ./myscript.sh -ssfss by mistake, it parses that like -ss -f ss, which is NOT desirable behavior!

How can I detect this? Ideally, I'd like to force that f parameter to be defined separately, and allow -f foo or -f=foo, but not -sf=foo or -sf foo.

Is this possible without doing something hairy? I imagine I could do something with a RegEx, along the lines of match $@ against something like -[^ef[:space:]]*[ef]{1}[ =](.*), but I'm worried about false positives (that regex might not be exactly right)

Thanks!



Solution 1:[1]

Here's what I've come up with. It seems to work, but I imagine the RegEx could be simplified. And I imagine there are edge cases I've overlooked.

validOpts="sf:e:"
optsWithArgs=$(echo "$validOpts" | grep -o .: | tr -d ':\n')

# ensure that options that require (or have optional) arguments are not combined with other short options
invalidOptArgFormats=( "[^$optsWithArgs[:space:]]+[$optsWithArgs]" "[$optsWithArgs]([^ =]|[ =]$|$)" )
IFS="|" && invalidOptArgRegEx="-(${invalidOptArgFormats[*]})"
[[ "$@" =~ $invalidOptArgRegEx ]] && echo -e "An option you provided takes an argument; it is required to have its option\n    on a separate - to prevent accidentally passing an opt as an argument.\n    (You provided ${BASH_REMATCH[0]})" && exit 1

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 user3534080