缺少选项参数时,Getopts 的行为不符合预期
Getopts behaves not as expected when option parameter is missing
我有一个带有五个位置参数的小脚本,其中前两个是可选的(-v
和 -p
),后三个是必需的(one
、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
参数
$ myscript -v -p one two three
它没有说'option -p requires an argument',而是将one
作为-p
的参数。显然不是我想要的。
我明白为什么会这样,但我不知道如何解决。
我建议在 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
我有一个带有五个位置参数的小脚本,其中前两个是可选的(-v
和 -p
),后三个是必需的(one
、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
参数
$ myscript -v -p one two three
它没有说'option -p requires an argument',而是将one
作为-p
的参数。显然不是我想要的。
我明白为什么会这样,但我不知道如何解决。
我建议在 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