Подтвердить что ты не робот

Использование getopts внутри функции Bash

Я хотел бы использовать getopts внутри функции, которую я определил в моем .bash_profile. Идея в том, что я хотел бы передать некоторые флаги этой функции, чтобы изменить ее поведение.

Здесь код:

function t() {
    echo $*
    getopts "a:" OPTION
    echo $OPTION
    echo $OPTARG
}

Когда я вызываю его так:

t -a bc

Я получаю этот вывод:

-a bc
?
 

Что случилось? Я бы хотел получить значение bc без ручного переключения и разбора. Как правильно использовать getopts внутри функции?

EDIT: исправлен фрагмент кода, чтобы попробовать $OPTARG, но безрезультатно

РЕДАКТИРОВАТЬ № 2: ОК получается, что код в порядке, моя оболочка была как-то испорчена. Открытие нового окна решило его. Значение arg действительно было в $OPTARG.

4b9b3361

Ответ 1

Как указывает @Ansgar, аргумент вашей опции хранится в ${OPTARG}, но это не единственное, что нужно учитывать при использовании getopts внутри функции. Вы также должны убедиться, что ${OPTIND} является локальным для функции, либо отменив ее, либо объявив ее local, иначе вы столкнетесь с неожиданным поведением при вызове функции несколько раз.

t.sh:

#!/bin/bash

foo()
{
    foo_usage() { echo "foo: [-a <arg>]" 1>&2; exit; }

    local OPTIND o a
    while getopts ":a:" o; do
        case "${o}" in
            a)
                a="${OPTARG}"
                ;;
            *)
                foo_usage
                ;;
        esac
    done
    shift $((OPTIND-1))

    echo "a: [${a}], non-option arguments: $*"
}

foo
foo -a bc bar quux
foo -x

Пример выполнения:

$ ./t.sh
a: [], non-option arguments:
a: [bc], non-option arguments: bar quux
foo: [-a <arg>]

Если вы прокомментируете # local OPTIND, вместо этого вы получите следующее:

$ ./t.sh
a: [], non-option arguments:
a: [bc], non-option arguments: bar quux
a: [bc], non-option arguments:

Кроме этого, его использование такое же, как при использовании вне функции.

Ответ 2

Вот простой пример getopts использования в функции оболочки:

#!/usr/bin/env bash
t() {
  local OPTIND
  getopts "a:" OPTION
  echo Input: $*, OPTION: $OPTION, OPTARG: $OPTARG
}
t "[email protected]"
t -a foo

Вывод:

$ ./test.sh -a bc
Input: -a bc, OPTION: a, OPTARG: bc
Input: -a foo, OPTION: a, OPTARG: foo

Как @Adrian указал, local OPTIND (или OPTIND=1) необходимо установить, так как оболочка не выполняет reset OPTIND автоматически между несколько вызовов на getopts (man bash).

Базовый синтаксис для getopts:

getopts OPTSTRING VARNAME [ARGS...]

и по умолчанию, не указывая аргументы, эквивалентно явному вызову его с "$ @", который: getopts "a:" opts "[email protected]".

В случае проблем это используемые переменные для getopts для проверки:

  • OPTIND - индекс для следующего обрабатываемого аргумента,
  • OPTARG - переменной присваивается любой аргумент для опции, найденной getopts,
  • OPTERR (не POSIX) - установите значение 0 или 1, чтобы указать, должно ли Bash отображать сообщения об ошибках, сгенерированные getopts.

Далее, см. Небольшой учебник по учебникам в Bash Hackers Wiki

Ответ 3

Аргумент сохраняется в переменной $OPTARG.

function t() {
  echo $*
  getopts "a:" OPTION
  echo $OPTION
  echo $OPTARG
}

Вывод:

$ t -a bc
-a bc
a
bc