如何使 bash getopts 无法将选项识别为选项参数
How make bash getopts not recognize option as a option argument
在我的 bash 脚本中,我想使用 getopts
来解析命令行选项。
我第一次尝试学习如何使用它,如下所示:
#!/bin/bash
v_option_arg=""
r_option_arg=""
h_option_arg=""
function get_opt_args() {
while getopts ":v:r:h:" opt
do
case $opt in
"v")
v_option_arg="$OPTARG"
;;
"h")
h_option_arg="$OPTARG"
;;
"r")
r_option_arg="$OPTARG"
;;
"?")
echo "Unknown option -$OPTARG"
exit 1
;;
":")
echo "No argument value for option -$OPTARG"
;;
*)
# Should not occur
echo "Unknown error while processing options"
;;
esac
done
shift $((OPTIND-1))
}
get_opt_args $@
if [ ! -z "$v_option_arg" ]; then
echo "Argnument value for option -v: $v_option_arg"
fi
if [ ! -z "$r_option_arg" ]; then
echo "Argnument value for option -r: $r_option_arg"
fi
if [ ! -z "$h_option_arg" ]; then
echo "Argnument value for option -h: $h_option_arg"
fi
$ bash testopts.sh -v 1
Argnument value for option -v: 1
$ bash testopts.sh -r 2
Argnument value for option -r: 2
$ bash testopts.sh -h 3
Argnument value for option -h: 3
$ bash testopts.sh -v 1 -r 2 -h 3
Argnument value for option -v: 1
Argnument value for option -r: 2
Argnument value for option -h: 3
$ bash testopts.sh -v
No argument value for option -v
$ bash testopts.sh -a
Unknown option -a
这似乎成功了。
接下来,我通过省略一个参数来测试我的脚本的健壮性:
$ bash testopts.sh -v -r 2
Argnument value for option -v: -r
这不是我所期待的。如何让它区分一个选项和一个选项参数的区别?
我想让我的脚本更健壮,这样如果给出一个没有参数的选项,我可以发出合适的错误消息。
注意:每个选项都必须有一个选项参数。
我可以只使用 getopts
吗?
来自 man bash
,SHELL 内置命令,getopts:
optstring contains the option characters to be recognized; if a character is followed by a colon, the option is expected to have an argument, which should be separated from it by white space.
来自您的脚本:
while getopts ":v:r:h:" opt
您明确告诉 bash
-v
需要一个参数。在 -v -r 2
的情况下,-r
是 -v
的参数,2
保留为脚本的非选项参数。
按设计工作,这是 getopts
能力的极限。
你 可以 做的是检查 -v
的参数是否是数字(因为这似乎是你的脚本所期望的),并在给定的情况下通知-v
确实的用户需要一个数字,而-r
不是。但这是您的脚本在 "v")
情况下需要做的事情,而不是 getopts
可以处理的事情。
case $opt in
"v")
v_option_arg="$OPTARG"
if [[ ! "${v_option_arg}" =~ ^[0-9]*$ ]]
then
echo "Error: Option '-v' expects numeric argument, you gave: ${v_option_arg}"
exit 1
fi
;;
在我的 bash 脚本中,我想使用 getopts
来解析命令行选项。
我第一次尝试学习如何使用它,如下所示:
#!/bin/bash
v_option_arg=""
r_option_arg=""
h_option_arg=""
function get_opt_args() {
while getopts ":v:r:h:" opt
do
case $opt in
"v")
v_option_arg="$OPTARG"
;;
"h")
h_option_arg="$OPTARG"
;;
"r")
r_option_arg="$OPTARG"
;;
"?")
echo "Unknown option -$OPTARG"
exit 1
;;
":")
echo "No argument value for option -$OPTARG"
;;
*)
# Should not occur
echo "Unknown error while processing options"
;;
esac
done
shift $((OPTIND-1))
}
get_opt_args $@
if [ ! -z "$v_option_arg" ]; then
echo "Argnument value for option -v: $v_option_arg"
fi
if [ ! -z "$r_option_arg" ]; then
echo "Argnument value for option -r: $r_option_arg"
fi
if [ ! -z "$h_option_arg" ]; then
echo "Argnument value for option -h: $h_option_arg"
fi
$ bash testopts.sh -v 1
Argnument value for option -v: 1
$ bash testopts.sh -r 2
Argnument value for option -r: 2
$ bash testopts.sh -h 3
Argnument value for option -h: 3
$ bash testopts.sh -v 1 -r 2 -h 3
Argnument value for option -v: 1
Argnument value for option -r: 2
Argnument value for option -h: 3
$ bash testopts.sh -v
No argument value for option -v
$ bash testopts.sh -a
Unknown option -a
这似乎成功了。
接下来,我通过省略一个参数来测试我的脚本的健壮性:
$ bash testopts.sh -v -r 2
Argnument value for option -v: -r
这不是我所期待的。如何让它区分一个选项和一个选项参数的区别?
我想让我的脚本更健壮,这样如果给出一个没有参数的选项,我可以发出合适的错误消息。
注意:每个选项都必须有一个选项参数。
我可以只使用 getopts
吗?
来自 man bash
,SHELL 内置命令,getopts:
optstring contains the option characters to be recognized; if a character is followed by a colon, the option is expected to have an argument, which should be separated from it by white space.
来自您的脚本:
while getopts ":v:r:h:" opt
您明确告诉 bash
-v
需要一个参数。在 -v -r 2
的情况下,-r
是 -v
的参数,2
保留为脚本的非选项参数。
按设计工作,这是 getopts
能力的极限。
你 可以 做的是检查 -v
的参数是否是数字(因为这似乎是你的脚本所期望的),并在给定的情况下通知-v
确实的用户需要一个数字,而-r
不是。但这是您的脚本在 "v")
情况下需要做的事情,而不是 getopts
可以处理的事情。
case $opt in
"v")
v_option_arg="$OPTARG"
if [[ ! "${v_option_arg}" =~ ^[0-9]*$ ]]
then
echo "Error: Option '-v' expects numeric argument, you gave: ${v_option_arg}"
exit 1
fi
;;