zsh `getopts` поведение OPTIND не соответствует другим оболочкам (bash, sh)

Определение $OPTIND в оболочке POSIX, 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)


person KFL    schedule 30.08.2020    source источник


Ответы (1)


Вас не должно сильно волновать значение 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

Всегда включайте local OPTIND в любую функцию, использующую getopts, иначе все getopts совместно используют один глобальный OPTIND

person Philippe    schedule 30.08.2020
comment
Спасибо. Я проголосовал. Хотя этот конкретный тип использования OPTIND работает, он по-прежнему не отвечает на мой первоначальный вопрос, почему. Сдвиг OPTIND-1 в конце цикла — не единственный способ использования getopts, это просто часто используемый шаблон. Таким образом, в тех случаях, когда OPTIND используется по-разному, мое беспокойство в исходном вопросе остается в силе, если только это поведение не будет понято более четко. - person KFL; 01.09.2020
comment
Можете ли вы привести пример использования, когда OPTIND используется по-другому и который не может быть охвачен шаблоном, который я дал? - person Philippe; 01.09.2020