Everything I see uses getopt
or the slightly-fancier getopts
which only supports one-character options (e.g., -h
but not --help
). I want to do fancy long options.
问题:
回答1:
I've done something like this:
_setArgs(){
while [ "${1:-}" != "" ]; do
case "$1" in
"-c" | "--configFile")
shift
configFile=$1
;;
"-f" | "--forceUpdate")
forceUpdate=true
;;
"-r" | "--forceRetry")
forceRetry=true
;;
esac
shift
done
}
As you can see, this supports both the single-character and the longer options nicely. It allows for values to be associated with each argument, as in the case of --configFile
. It's also quite extensible, with no artificial limitations as to what options can be configured, etc.
As included above, the "${1:-}"
prevents an "unbound variable" error when running in bash "strict" mode (set -euo pipefail
).
回答2:
Assuming that you "want to do fancy long options" regardless of the tool, just go with getopt
(getopts
seems to be mainly used when portability is crucial). Here's an example of about the maximum complexity that you'll get:
params="$(getopt -o e:hv -l exclude:,help,verbose --name "$(basename "$0")" -- "$@")"
if [ $? -ne 0 ]
then
usage
fi
eval set -- "$params"
unset params
while true
do
case $1 in
-e|--exclude)
excludes+=("$2")
shift 2
;;
-h|--help)
usage
;;
-v|--verbose)
verbose='--verbose'
shift
;;
--)
shift
break
;;
*)
usage
;;
esac
done
With this code, you can specify -e
/--exclude
more than once, and ${excludes[@]}
will contain all of the given excludes. After processing (--
is always present) anything remaining is stored in $@
.