如何使 bash getopts 不将选项识别为选项参数

loj*_*ren 1 bash getopts

在我的 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
Run Code Online (Sandbox Code Playgroud)
#!/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
Run Code Online (Sandbox Code Playgroud)

这似乎工作成功。

接下来,我通过省略参数来测试脚本的稳健性:

$ bash testopts.sh -v -r 2
Argnument value for option -v: -r
Run Code Online (Sandbox Code Playgroud)

这不是我所期待的。如何让它区分一个选项和一个选项参数的差异?

我想让我的脚本更加健壮,这样如果给出一个没有参数的选项,我可以发出一条合适的错误消息。

注意:每个选项都必须有一个选项参数。

我可以用 来做到这一点getopts吗?

Dev*_*lar 6

man bashshell 内置命令中,getopts:

optstring 包含要识别的选项字符;如果一个字符后面跟着一个冒号,则该选项应该有一个参数,该参数应该用空格与其分隔。

从你的脚本:

while getopts ":v:r:h:" opt
Run Code Online (Sandbox Code Playgroud)

bash你明确地告诉我们-v需要争论。在 的情况下-v -r 2-r是 的参数-v2其余作为脚本的非选项参数。

按照设计工作,这是能力的极限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
         ;;
Run Code Online (Sandbox Code Playgroud)