Использование 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.
Ответы
Ответ 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