我是 shell 新手,我试图编写一个接受常规参数的自定义函数,并解析提供的任何标志。
test_it() {
flag1="false"
flag2="false"
while getopts "ab" opt; do
case ${opt} in
a) flag1="true" ;;
b) flag2="true" ;;
*) break ;;
esac
done
echo $flag1 $flag2
shift "$(($OPTIND - 1))"
echo "Custom param: $1"
}
但是,如果我在标志后提供自定义参数,则此函数只能按我想要的方式工作。如果我要在标志之前提供自定义参数,它不会解析标志。
> test_it -ab foo
true true
Custom param: foo
> test_it foo -ab
false false
Custom param: foo
> test_it -a foo -b
true false
Custom param: foo
有没有一种方法可以使标志和参数无论顺序如何都能正确解析?换句话说,它应该true true
在所有这三种情况下回显这两个标志,因为它们是在函数调用期间的某个时刻被调用的?这应该是可能的,因为我观察到函数喜欢rsync
这样做。
答案1
是的:在函数中,在调用之前while getopts
添加
local OPTIND OPTARG
每次都会将“计数器”重置为 0。
另请注意,这while getopts
将在第一个非选项处停止。如果你想test foo -ab
工作,你需要使用getopt(1)
(getopt
示例脚本)
test_it() {
local tmp flag1=false flag2=false
tmp=$(getopt -o 'ab' -n "$FUNCNAME" -- "$@")
local rc=$?
((rc == 0)) || return $rc
eval set -- "$tmp"
while true; do
case "$1" in
'-a') flag1=true
shift
;;
'-b') flag2=true
shift
;;
'--') shift
break
;;
*) echo Internal Error >&2
return 1
;;
esac
done
declare -p flag1 flag2
echo "Remaining params:"
printf "%s\n" "$@"
}
$ test_it foo -a bar -b
declare -- flag1="true"
declare -- flag2="true"
Remaining params:
foo
bar
$ test_it -a quz
declare -- flag1="true"
declare -- flag2="false"
Remaining params:
quz
$ test_it baz -b
declare -- flag1="false"
declare -- flag2="true"
Remaining params:
baz
$ test_it -c
test_it: invalid option -- c
$ test_it baz --ab
test_it: unrecognized option `--ab'