我有一个小脚本,它接受五个位置参数,前两个是可选的(-v
和-p
),后三个是必需的(one
,{{1} },two
)。第二个可选参数采用参数。到目前为止,我有这个:
three
现在,如果我运行应该运行的脚本,它的行为符合预期:
#!/bin/bash
verbose=
altpath=
while getopts ":vp:" opt; do
case $opt in
v) echo "-v triggered"
verbose=true
;;
p) echo "-p triggered, param: $OPTARG"
altpath=$OPTARG
;;
\?) echo "invalid option: -$OPTARG."
exit 1
;;
:) echo "option -$OPTARG requires an argument."
exit 1
;;
esac
done
shift "$((OPTIND-1))"
但是,如果我忘记了$ myscript -v -p argname one two three
参数
argname
它没有说'选项-p需要参数',而是将$ myscript -v -p one two three
作为one
的参数。显然,不是我想要的。
我理解为什么会这样,但我无法弄清楚如何解决它。
答案 0 :(得分:2)
我建议测试一旦getopts完成其工作后是否还有三个未处理的参数。如果不是这种情况,则中止并打印错误消息。
例如,在脚本末尾添加:
shift "$((OPTIND-1))"
if [ ! $# -eq 3 ] ; then
echo "Expected three mandatory arguments"
exit 1
fi
如果省略-p
的参数,则强制发生错误,不直接支持。作为解决方法,您可以测试下一个参数是丢失还是以破折号开头。例如:
p) if [ -z "$OPTARG" -o "${OPTARG:0:1}" = "-" ] ; then
echo "Error: -p requires an argument"
exit 1
fi
echo "-p triggered, param: $OPTARG"
altpath=$OPTARG
;;
以下是完整的脚本:
#!/bin/bash
verbose=
altpath=
while getopts ":vp:" opt; do
case $opt in
v) echo "-v triggered"
verbose=true
;;
p) if [ -z "$OPTARG" -o "${OPTARG:0:1}" = "-" ] ; then
echo "Error: -p requires an argument"
exit 1
fi
echo "-p triggered, param: $OPTARG"
altpath=$OPTARG
;;
\?) echo "invalid option: -$OPTARG."
exit 1
;;
:) echo "option -$OPTARG requires an argument."
exit 1
;;
esac
done
shift "$((OPTIND-1))"
if [ ! $# -eq 3 ] ; then
echo "Expected three mandatory arguments"
exit 1
fi