zsh的`getopts`命令在OPTIND行为上与其他shell(如bash、sh)不一致

3
$OPTIND在POSIX shell和bash中的定义非常一致且直观 - 它是下一个要读取的参数的索引。但是,在zsh中它的行为相当令人困惑,我找不到相关的文档说明。
示例:
# ./test.sh:
foo() {
    while getopts "1:2:34:" flag; do
        echo flag: $flag
        echo arg: $OPTARG
        echo ind: $OPTIND
    done &&
    echo .
}

foo -1 1 -2 2 -3 3 -4 4

现在执行:

>>> sh ./test.sh
flag: 1
arg: 1
ind: 3
flag: 2
arg: 2
ind: 5
flag: 3
arg:
ind: 6    <<<< EXPECTED - next arg should be $6
.

>>> bash ./test.sh
flag: 1
arg: 1
ind: 3
flag: 2
arg: 2
ind: 5
flag: 3
arg:
ind: 6    <<<< EXPECTED - next arg should be $6
.

>>> zsh ./test.sh 
flag: 1
arg: 1
ind: 3
flag: 2
arg: 2
ind: 5
flag: 3
arg:
ind: 5   <<<<<< NOTICE HERE
.

这是在 zsh 5.3.1 (amd64-portbld-freebsd11.0) 上测试的。

1个回答

2

您不需要过于关注OPTIND的值。

重要的是在处理完所有选项后的下一个参数:

以下结构对于bash和zsh都适用:

# ./test.sh:
foo() {
    local OPTIND flag
    while getopts "1:2:34:" flag; do
        echo flag: $flag
        echo arg: $OPTARG
        echo ind: $OPTIND
    done 
    shift $(( OPTIND - 1 ))
    echo "Next arg is $1"
}

foo -1 1 -2 2 -3 3 -4 4

在使用 getopts 函数的任何函数中,始终包含 local OPTIND,否则所有 getopts 将共享一个全局 OPTIND


谢谢。我已经点赞了。虽然这种使用OPTIND的方式有效,但它仍然没有回答我的原始问题:为什么要这样做。将OPTIND-1移到循环末尾并不是使用getopts的唯一方法,只是一个常用的模式。因此,在使用OPTIND的其他情况下,我对原始问题的担忧仍然存在,除非这种行为被更清楚地理解。 - KFL
你能给出一个使用OPTIND的不同用例的示例吗?这个示例不能被我提供的模式所覆盖。 - Philippe
那个解决方案对我没有用。在zsh中,getopts仍然不可靠。我使用了while循环代替getopts - t7e

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接