На операционных системах семейства Unix (Linux, FreeBSD и т. п.) в скриптах шелла bash работает команда getopts. Она анализирует (парсит) опции и аргументы команды, которые были переданы в скрипт bash.
[Описание команды getopts]
Утилита getopts это bash-версия другой системной утилиты, getopt [3, 4]. Обратите внимание, что имя команды bash отличается от имени getopt только буквой s в конце.
В то время как системная утилита getopt может меняться от системы к системе, bash-команда определена стандартом POSIX. Так что если вы напишете скрипт, используя getopts, то можете быть уверенным, что он будет работать на любой системе, где bash запускается в режиме POSIX (например set -o posix).
Команда getopts парсит короткие опции, которые начинаются с одного дефиса (-), за которым идет буква или цифра. Примеры коротких опций: -2, -d и -D. Она также может парсить комбинации коротких опций, например -2dD (это то же самое, как три одновременно указанные опции -2, -d и -D).
Однако getopts не может парсить опции с длинными именами. Если вы хотите обрабатывать опции наподобие --verbose или --help, то используйте getopt.
[Синтаксис getopts]
getopts optstring optname [ arg ]
Как это работает. Команда getopts обрабатывает позициональные параметры родительской команды (скрипта). В bash они сохраняются в переменной шелла $@. Так что если вы запустите команду:
$ mycmd -a argument1 -b argument2
.. то во время работы команды mycmd в переменной $@ содержится строка "-a argument1 -b argument2". Вы можете использовать getopts для парсинга этой строки для получения опций и аргументов команды.
Каждый раз, когда вы запускаете команду getopts, она ищет одну из опций, определенных в строке опций (optstring). Если опция найдена, то буква опции помещается в переменную с именем optname. Если опция не соответствует чему-либо, что определено в optstring, то getopts установит переменную optname в символ знака вопроса (?).
Если у опции ожидается аргумент, то getopts берет этот аргумент и помещает его в переменную $OPTARG. Если ожидаемый аргумент не обнаружен, то переменная optname установится в символ двоеточия (:). Затем getopts инкрементирует позициональный индекс $OPTIND, что показывает обработку следующей опции.
Специальная опция из двух дефисов (--) интерпретируется getopts как конец опций.
Команда getopts разработана так, чтобы использоваться в скрипте несколько раз, например в теле цикла while. Тогда она будет обрабатывать по одной опции за одну итерацию цикла. Когда больше нет опций для обработки, getopts вернет false, что автоматически завершит работу цикла while. Поэтому getopts и while часто используются вместе.
Как указывать строку опций optstring. Под optstring подразумевается строка, которая определяет, какие опции и аргументы должна искать getopts. Например, в следующем вызове getopts:
.. ожидается наличие опций -a, -p и -Z без аргументов. Эти опции могут комбинироваться друг с другом в любом порядке, как например -aZ, -pa, -Zap, и т. п.
Предположим, что вам нужно для опций -a и -Z обрабатывать аргументы. Для этого после символа опций указывают двоеточие (:), например:
Теперь для опций -a и -Z можно указывать аргументы, такие как -a argument1 -pZ argument2. Опция -p не может принимать аргументы, потому что после буквы p не было указано двоеточие в optstring.
Важное замечание: зарезервированы два специальных символа, которые нельзя использовать в качестве опций: двоеточие (:) и знак вопроса (?).
Тщательная или тихая проверка ошибок. По умолчанию getopts подробно сообщает от ошибке, если найдет неизвестную опцию или неправильно указанный аргумент. Также getopts установит значение optname в знак вопроса (?) и не присвоит значение для $OPTARG.
Если опция определена, но ожидаемый аргумент опции не найден, то optname установится в "?", переменная $OPTARG становится неустановленной, и будет выведено подробное сообщение об ошибке.
Однако если вы поместите двоеточие в начало optstring, то getopts запустится в режиме тихой проверки ошибок, "silent error checking mode". Она не будет подробно сообщать об ошибках в опциях или аргументах, и тогда в скрипте придется самостоятельно реализовать проверку ошибок.
В silent-режиме если встретилась неожиданная опция, то getopts усиновит optname в "?" и $OPTARG в символ неизвестной опции.
Если опция нормальная, но её ожидаемый аргумент не найден, то optname установится в двоеточие (:), и $OPTARG установится в неизвестный символ опции.
Указание пользовательских аргументов. Вы обычно захотите, чтобы getopts обрабатывала аргументы в $@, однако в некоторых случаях может потребоваться предоставлять аргументы вручную для парсинга getopts. Тогда вы можете указать эти аргументы как последний аргумент в команде getopts.
[Примеры использования getopts]
В следующем bash-скрипте используется getopts. Этот скрипт напечатает приветствие с опциональным именем различное количество раз. Он принимает две возможные опции: -n NAME и -t TIMES.
#!/bin/bash
NAME="" # Имя того, кого приветствуем.
TIMES=1 # Количество выдаваемых приветствий.
usage() { # Функция печати сообщения подсказки.
echo "Usage: $0 [ -n NAME ] [ -t TIMES ]" 1>&2
}
exit_abnormal() { # Функция для выхода в случае ошибки.
usage
exit 1
}
while getopts ":n:t:" options; do # Цикл: выбора опций по одной,
# с использованием silent-проверки
# ошибок. Опции n и t должны
# принимать аргументы.
case "${options}" in #
n) # Если это опция n, то установка
NAME=${OPTARG} # $NAME в указанное значение.
;;
t) # Если это опция t, то установка
TIMES=${OPTARG} # $TIMES в указанное значение.
re_isanum='^[0-9]+$' # Regex: ожидается совпадение
# только с цифрами.
if ! [[ $TIMES =~ $re_isanum ]] ; then # если $TIMES не целое число:
echo "Error: TIMES must be a positive, whole number."
exit_abnormal
elif [ $TIMES -eq "0" ]; then # Если $TIMES ноль:
echo "Error: TIMES must be greater than zero."
exit_abnormal # Ненормальный выход.
fi
;;
:) # Если ожидаемый аргумент опущен:
echo "Error: -${OPTARG} requires an argument."
exit_abnormal # Ненормальный выход.
;;
*) # Если встретилась неизвестная опция:
exit_abnormal # Ненормальный выход.
;;
esac
done
if [ "$NAME" = "" ]; then # Если $NAME пустая строка,
STRING="Hi!" # то приветствие это просто "Hi!".
else # Иначе выведется
STRING="Hi, $NAME!" # "Hi, (name)!"
fi
COUNT=1 # Счетчик.
while [ $COUNT -le $TIMES ]; do # Пока счетчик меньше или равен
echo $STRING # $TIMES, печатать приветствие,
let COUNT+=1 # после чего увеличить счетчик.
# then increment the counter.
done
exit 0 # Нормальное завершение.
Предположим, что файл этого скрипта получил имя greeting. Ниже показаны варианты его запуска с различными опциями.
$ ./greeting
Hi!
$ ./greeting -n Dave
Hi, Dave!
$ ./greeting -t 3
Hi!
Hi!
Hi!
$ ./greeting -t 4 -n Betty
Hi, Betty!
Hi, Betty!
Hi, Betty!
Hi, Betty!
$ ./greeting -n
Error: -n requires an argument.
Usage: ./greeting [ -n NAME ] [ -t TIMES ]
$ ./greeting -t
Error: -t requires an argument.
Usage: ./greeting [ -n NAME ] [ -t TIMES ]
$ ./greeting -t -1
Error: TIMES must be a positive, whole number.
Usage: ./greeting [ -n NAME ] [ -t TIMES ]
$ ./greeting -t 0
Error: TIMES must be greater than zero.
Usage: ./greeting [ -n NAME ] [ -t TIMES ]
[Ссылки]
1. Bash getopts builtin command site:computerhope.com. 2. Bash: встроенная команда shift. 3. getopt разбор командной строки, получение опций site:opennet.ru. 4. getopt(3) Linux manual page site:man7.org. 5. Linux set and unset site:computerhope.com. |