如何使用 getopts 使用插入的值

如何使用 getopts 使用插入的值

我将这个 bash 代码与 getopts 结合起来,如果我正确理解了 getopts,OPTIND 包含下一个命令行选项的索引,并且提供给 shell 脚本的所有命令行选项都显示在变量 $1、$2、$3 等中。如果是,请纠正我我错了,但与函数中的局部变量的概念基本上相同。

所以根据这个为什么选项 [-a somevalue ]不会[-b somevalue ]给我任何结果。我究竟做错了什么?

OPT_A=A
OPT_B=B

while getopts :a:b FLAG; do
 case $FLAG in
    a) 
      OPT_A=$OPTARG
      ;;
    b) 
     OPT_B=$OPTARG
      ;;
  esac
done

shift $((OPTIND-1))

    while [ $# -ne 0 ]; do

if [[ -z $OPT_A ]]; then
    if [ `echo $1 | grep -o '\.' | wc -l` -ne 3 ]; then
        echo "Parameter '$1' does not look like an IP Address (does not contain 3 dots).";
            exit 1;
        elif [ `echo $1 | tr '.' ' ' | wc -w` -ne 4 ]; then
            echo "Parameter '$1' does not look like an IP Address (does not contain 4 octets).";
        exit 1;
            else
        for OCTET in `echo $1 | tr '.' ' '`; do
                if ! [[ $OCTET =~ ^[0-9]+$ ]]; then
                        echo "Parameter '$1' does not look like in IP Address (octet '$OCTET' is not numeric).";
                        exit 1;
                elif [[ $OCTET -lt 0 || $OCTET -gt 255 ]]; then
                        echo "Parameter '$1' does not look like in IP Address (octet '$OCTET' in not in range 0-255).";
                        exit 1;
                fi
        done
    fi
fi


if [[ -z $OPT_B ]]; then
        if [[ "$2" =~ ^[0-9]+$ ]] && [ "$2" -ge 1 -a "$2" -le 10000 ]; then 
            echo "chosen variable: $2";
            exit 1;
            else echo "variable $2 is not in range '1 - 10000'";
            exit 1;
        fi
    fi

    done
    exit 0

答案1

这是因为你的所有逻辑都依赖于其中之一$OPT_[AB]为空。但即使您不传递参数-[ab] $OPTARG,您仍然可以使用OPT_[AB]=[AB].所以你的逻辑链永远不会越过根源......

if [[ -z $OPT_A ]]; then...

...陈述。

嗯……不是全部你的逻辑取决于此。你也在做:

shift $((OPTIND-1))

    while [ $# -ne 0 ]...

所以如果你通过了,script -a arg那么getopts就会设置$OPT_Aarg3。$OPTIND所以你会shift 2 (你所有的职位)然后立即通过测试失败while。所以你case会设定$OPT_A,接下来发生的事情是exit 0。所以我猜你永远也不会去检查$OPT_A是否有空的。

即使这样也没关系,因为你的大部分逻辑都是为了测试失败而设计的 - 但你的脚本仅有的 exits。你可能做了$OPT_Avar,但你没有用它做任何事情。你不能在 script 后使用该值exit- 没有一些预设的 IPC,但这里没有这些。该脚本在子 shell 中调用,并且当它返回到父 shell 时,它设置的值将丢失。

更重要的是 optstring:a:b不允许$OPTARGto -b。 optstring 中的前导冒号表示安静操作 -stderr如果选项或其参数存在问题,它不会写入。但是一个冒号尾随选项字符表示该选项应该有一个参数。喜欢:

while getopts :a:b: FLAG

...这将表明两个需要参数的选项。但这可能很棘手,因为如果您指示它应该接受一个参数,那么如果getopts发现它没有参数,则会将其标记为错误:

sh -c 'getopts :a:b: opt -a; echo "$opt $OPTARG"'

...打印...

: a

在这种情况下,期权最终结果为$OPTARG:最终结果为$opt。如果我们:对此不那么沉默的话就会更清楚:

sh -c 'getopts a:b: opt -a; echo "$opt $OPTARG"'
No arg for -a option

因此,您需要检查:冒号和?- 这是另一种类型的错误,通常会重新路由以打印一些简短的--help内容。

就我个人而言,我会确保$OPT_[AB]一开始都是空的,执行一些逻辑来正确设置它们,并且在完成测试循环后,将我的最后一个测试设置为空值。如果它们根本没有任何价值,那么它一定是由于某种我没有处理的原因,无论如何它都是一个错误。这是我将如何进行测试循环的开始......

param_err(){
    set '' "$@"
    : "${1:?Parameter '$OPTARG' does not look like an IP Address $2}"
}

test_oct(){ 
    oIFS=$IFS; unset "${IFS+o}oIFS"; IFS=.
    for oct in $1; do  [ $oct -lt 256 ] || 
        param_err "('$oct' too large)"
    done; unset IFS oct
    : "${oIFS+${IFS=$oIFS}}"
}

a_param()
    case ${1##*.*.*.*.*} in (a) OPT_A=A;;  #some default - no arg provided                                            
          (.*|*..*|*.) param_err '(empty octet)';;
          (*[!.0-9]*)  param_err '(octet is not positive integer)';;
          (*.*.*.*)    test_oct  "$1"; OPT_A=$1;;
          (*?*)        param_err '(too few octets)';;
          (*)          param_err ${1:+"(too many octets)"} '(null param)';;
    esac

unset OPT_A OPT_B
while getopts :a:b:c:d: opt
do    case ${opt#:}$OPTARG in
      a*)   a_param "$OPTARG";;
      b*)   b_param "$OPTARG";; #tests as needed similar to a_param()
      ?*)   help;;              #param_err should call this too, but it just exits
      esac
done                

答案2

顶部没有 shebang 行,因此您使用的 shell ( sh, dash) 可能不支持[[。您应该使用以下命令启动脚本:

#!/bin/bash

或任何其他位置bash,在不太可能的情况下,这不是系统上 bash 的路径 ( type bash)。

答案3

尝试更改此设置: while getopts :a:b FLAG;做

对此: while getopts :a:b: FLAG;做

相关内容