I'm trying to use getopts for a bash script. This script can have flags and all of those flags are mandatory and need to contain a value. When one of the mandatory flags that supposed to contain a value is empty getopts use the next-in-line flag as his content. How do I prevent this?
This is my example:
#!/bin/bash
while getopts "A:B:" OPTION
do
case $OPTION in
A)
GILIA="$GILIA $OPTARG"
echo GILIA $GILIA
;;
B)
GILIB="$GILIB $OPTARG"
echo GILIB $GILIB
;;
esac
done
When using both flags with value:
./test_opt2 -A aaa -B bbb
GILIA aaa
GILIB bbb
When using "-A" flag empty:
./test_opt2 -A -B bbb
GILIA -B
I know that this is normal/typical behavior of getopts and I'm sure there is a way to go around this...
Any ideas?
Updated: 02/01/2021 by Computer Hope. On Unix-like operating systems, getopts is a builtin command of the Bash shell. It parses command options and arguments, such as those passed to a shell script.
The getopts command is a Korn/POSIX Shell built-in command that retrieves options and option-arguments from a list of parameters. An option begins with a + (plus sign) or a - (minus sign) followed by a character. An option that does not begin with either a + or a - ends the OptionString.
An option character in this string can be followed by a colon (' : ') to indicate that it takes a required argument. If an option character is followed by two colons (' :: '), its argument is optional; this is a GNU extension. getopt has three ways to deal with options that follow non-options argv elements.
According to man getopts , OPTIND is the index of the next argument to be processed (starting index is 1). Hence, In sh foo.sh -abc CCC Blank arg1 is -abc , so after a we are still parsing arg1 when next is b ( a 1 ).
Assuming: (1) all options are required and (2) no argument can start with '-' then I will use something like this:
while getopts ":a:b:" opt ; do
[[ ${OPTARG} == -* ]] && { echo "Missing argument for -${opt}" ; exit 1 ; }
case ${opt} in
a ) gilia="$gilia $OPTARG"
echo gilia $gilia
;;
b ) gilib="$gilib $OPTARG"
echo gilib $gilib
;;
\?) echo "Invalid (-${OPTARG}) option"
;;
: ) echo "Missing argument for -${OPTARG}"
;;
esac
done
You will get:
$ ./t.sh -a aaa -b bbb
gilia aaa
gilib bbb
$ ./t.sh -a -b bbb
Missing argument for -a
$ ./t.sh -a aaa -b
gilia aaa
Missing argument for -b
$ ./t.sh -a aaa -b bbb -c ccc
gilia aaa
gilib bbb
Invalid (-c) option
What you could do is to check the value of $OPTARG. If it starts with -
, decrease the value of the index $OPTIND, so that the -
parameter is picked up as the OPTION next time round the loop.
In your second example, when processing the empty -A argument, $OPTIND will be set to 3. My code will set the value back to 2 so that -B
will be processed next.
case $OPTION in
A)
arg=${OPTARG#-}
if [ $arg == $OPTARG ]
then
GILIA="$GILIA $OPTARG"
echo GILIA $GILIA
else
echo "-A needs argument"
OPTIND=$OPTIND-1
fi
;;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With