我看到的所有内容都使用getopt
或稍微有点getopts
的{{1}},它只支持单字符选项(例如-h
但不支持--help
)。我想做很长的选择。
答案 0 :(得分:14)
我做过类似this的事情:
_setArgs(){
while [ "${1:-}" != "" ]; do
case "$1" in
"-c" | "--configFile")
shift
configFile=$1
;;
"-f" | "--forceUpdate")
forceUpdate=true
;;
"-r" | "--forceRetry")
forceRetry=true
;;
esac
shift
done
}
正如您所看到的,这可以很好地支持单字符和更长的选项。它允许将值与每个参数相关联,如--configFile
的情况。它也是相当可扩展的,没有人为限制,可以配置哪些选项等。
如上所述,{b}“严格”模式("${1:-}"
)运行时,set -euo pipefail
可防止出现“未绑定变量”错误。
答案 1 :(得分:7)
假设您“想要做出花哨的长选项”,无论使用哪种工具,只需使用getopt
(getopts
似乎主要用于便携性至关重要)。这是关于您将获得的最大复杂性的example:
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
使用此代码,您可以多次指定-e
/ --exclude
,${excludes[@]}
将包含所有给定的排除。处理完毕后(--
始终存在)剩余的任何内容都存储在$@
。
答案 2 :(得分:0)
我创建了一个bash函数,该函数最易于使用并且不需要自定义。只需使用该函数并传递所有带有或不带有参数的长选项,该函数就会将它们设置为变量,并在脚本中将相应的选项参数作为值。
function get_longOpt {
## Pass all the script's long options to this function.
## It will parse all long options with its arguments,
## will convert the option name to a variable and
## convert its option value to the variable's value.
## If the option does not have an argument, the
## resulting variable's value will be set to true.
## Works properly when providing long options, only.
## Arguments to options may not start with two dashes.
##
#### Usage
##
## get_longOpt $@
##
## May expand to:
##
## get_longOpt --myOption optimopti --longNumber 1000 --enableMe --hexNumber 0x16
##
### Results in the bash interpretation of:
## myOption=optimopti
## longNumber=1000
## enableMe=true
## hexNumber=0x16
##
local -a opt_list=( $@ )
local -A opt_map
local -i index=0
local next_item
for item in ${opt_list[@]}; do
# Convert arg list to map.
let index++
next_item="${opt_list[$index]}"
if [[ "${item}" == --* ]] \
&& [[ "${next_item}" != --* ]] \
&& [[ ! -z "${next_item}" ]]
then
item="$(printf '%s' "${item##*-}")"
opt_map[${item}]="${next_item}"
elif [[ "${item}" == --* ]] \
&& { [[ "${next_item}" == --* ]] \
|| [[ -z "${next_item}" ]]; }
then
item="$(printf '%s' "${item##*-}")"
opt_map[${item}]=true
fi
done
for item in ${!opt_map[@]}; do
# Convert map keys to shell vars.
value="${opt_map[$item]}"
[[ ! -z "${value}" ]] && \
printf -v "$item" '%s' "$value"
done
}
可在此处获取最新的原始源代码:
https://github.com/theAkito/akito-libbash/blob/master/bishy.bash