缺少选项参数时,Getopts的行为与预期不符

时间:2017-04-15 11:36:19

标签: bash getopts

我有一个小脚本,它接受五个位置参数,前两个是可选的(-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的参数。显然,不是我想要的。

我理解为什么会这样,但我无法弄清楚如何解决它。

1 个答案:

答案 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