Closed odkr closed 2 weeks ago
The shift $((OPTIND - 1))
idiom is only valid after getopts has processed all options. You should not expect $OPTIND to have a portable value until getopts returns a non-zero exit status. Consider this script:
while getopts :ab opt -a -aXb -b x; do
if [ "$opt" = "?" ]; then
echo $OPTIND
fi
done
Bash and ksh show 2
while busybox, dash, and mksh show 3
. Zsh even seems to change its behavior depending on the emulation mode.
The current behavior of yash works as a reminder that the $OPTIND value shouldn't be relied upon, so I would decline to change the behavior.
P.S.
You don't necessarily have to break
when you encounter an unknown option. You can keep calling getopts to let it process the remaining options.
Thanks for the quick reply and the example! And while I'm thanking you, also thank you for Yash. I had tested my MWE with bash, dash, and mksh, and in that case they just happen to agree. And since the MWE is derived from a script that is also tested with other shells, I wrongly inferred that the behavior is uniform. My bad.
Description
In Yash 2.57, when an option is encountered by
getopts
that is not specified in the option string, then OPTIND is set to "n:m", where n is the index of the last option and m is some other number, the value of which does not follow a rule I could discern (in the MWE given below it happens to always be 2).While POSIX.1 does not specify what OPTIND should be set to when an option is encountered by
getopts
that is not specified in the option string, the current behavior breaks theshift $((OPTIND - 1))
idiom and differs from mainstream shells (I've compared it to the ash, bash, dash, ksh, mksh, oksh, and zsh).MWE
prints
Expected behaviour
prints
Environment