getopts

http://citforum.ru/operating_systems/GETOPTS

https://www.opennet.ru/docs/RUS/bash_scripting/GETOPTS

https://www.mkssoftware.com/docs/man1/GETOPTS

https://itsecforu.ru <---------

Команда (метод) shift по замещению параметров,безусловно расширяет возможности работы с переменными, но что не может сделать shift это обработать различные опции командной строки например: conmand -1 -с 2 -v file1 file2

А вот метод getopts, занимается тем что разбирает позиционные параметры и проверяет опции на допустимость, то есть используется для разбора аргументов, передаваемых скрипту из командной строки. Getopts (название говорит само за себя) одна из команд по обработке аргументов, как например и xarg, повышающие возможность языка оболочки и гибкость кода и как следствие позволяет радикально сократить его объем (в сравнении с методом shift).

Проше говоря исторически у команды есть аргументы и опции и некоторые из переданных аргументов могут быть опциями, это "переключатели" в виде одиночных символов, отличающиеся от других параметров стоящей перед ними дефисом, ключи это еще одно название для них, и чтобы использовать те же методы в скриптах shell, используют команду getopts .

Итак - getopts синтаксический разбор аргументов (параметров) опций.

Команда getopts используется процедурами командного интерпретатора для разбора позиционных параметров. Аргумент, строка опций содержит символы опций, которые необходимо распознать; если после опции указано двоеточие (:) - флаг, предполагается, что у опции должен быть аргумент, отделяемый от неё пробельным символом. При каждом вызове команда getopts помещает в переменную интерпретатора с указанным именем ($name) очередную опцию, создавая переменную, если она ещё не существует, а индекс следующего аргумента — в переменную $OPTIND. Переменная $OPTIND получает значение 1 при каждом вызове командного интерпретатора или сценария. Если опция должна иметь аргумент, команда getopts помещает этот аргумент в переменную $OPTARG.

Командный интерпретатор не сбрасывает значение $OPTIND автоматически. Между вызовами команды getopts в том же командном интерпретаторе, если необходимо использовать новый набор параметров, надо сбрасывать это значение явно. Когда все опции обработаны, команда getopts завершает работу со значением, большим нуля. Переменная $OPTIND при этом содержит индекс первого аргумента, не являющегося опцией, а аргумент имя (name) получает значение "?". Команда getopts обычно обрабатывает позиционные параметры ($0-$9), но если заданы аргументы, getopts разбирает их.

Команда getopts может сообщать об ошибках двумя способами.

    • Если первый символ строки опций (optstring) — двоеточие (:), используется немногословное информирование об ошибках. При обычной работе выдаются диагностические сообщения, если обнаруживаются недопустимые опции или недостающие аргументы.

    • Если переменная $OPTERR имеет значение 0, сообщения об ошибках не выдаются, даже если первым символом строки опций не является двоеточие (:).

    • Если обнаружена недопустимая опция, getopts помещает "?" в аргумент имя (name) и, если не задано немногословное информирование, выдает сообщение об ошибке и сбрасывает переменную $OPTARG. Если getopts работает в режиме немногословного информирования, символ опции помещается в переменную $OPTARG и никакие диагностические сообщения не выдаются.

    • Если обязательный аргумент (arg) не обнаружен, и для getopts не задано немногословное информирование, аргумент имя (name) получает значение "?", переменная $OPTARG сбрасывается, и выдается диагностическое сообщение.

    • Если getopts работает в режиме немногословного информирования, аргумент имя получает значение ":", а в переменную $OPTARG помещается символ опции.

синтаксис: getopts optstring name [arg]

И конечно понять работу команды лучше всего на основе примеров. Ниже простой сценарий getopts, использующий следующие параметры, или аргументы:

-a Переменной ALL присваивается значение "истина"

-h Переменной HELP присваивается значение "истина"

-f Переменной FILE присваивается значение "истина"

-v Переменной VERBOSE присваивается значение "истина"

Общий формат команды getopts: getopts [строка_параметров] [переменная]

При определении каждой одиночной опции указание дефиса не требуется (-abcde). При всех установках переменных всегда предполагается худший вариант, поэтому изначально переменным присваивается значение "false":

$ ~ vim getopt1

#/bin/sh

#getopt1

# присвоение значений переменным

ALL=false

HELP=false

FILE=false

VERBOSE=false

while getopts ahfgv: OPTION; do

case $OPTION in

a)ALL=true

echo "ALL is $ALL" ;;

h)HELP=true

echo "HELP is $HELP" ;;

f)FILE=true

echo "FILE is $FILE" ;;

v)VERBOSE=true

echo "VERBOSE is $VERBOSE" ;;

esac

done

$

*** Двойные кавычки записывают обычно в новой строке, если одной строкой надо поставить пробел, без пробела то же сойдет, но в зависимости от версии getopts

При выполнении сценария с корректными и некорректными опциями получаются следующие результаты:

$ ~ getopt1 -a -h

ALL is true

HELP is true

$ ~ getopt1 -ah

ALL is true

HELP is true

$ ~ getopt1 -a -h -j -u -i -o

ALL is true

HELP is true

/home/getopt1: недопустимый параметр — j

/home/getopt1: недопустимый параметр — u

/home/getopt1: недопустимый параметр — i

/home/getopt1: недопустимый параметр — o

$ ~

Команда getopts считывает строку [строка_параметров]. При этом она выбирает корректные опции, которые могут быть применены в сценарии. Команда getopts разыскивает все аргументы, начинающиеся дефисом, и определяет значения всех опций. Затем значение опции сравнивается со строкой [строка_параметров]. Если соответствие установлено, переменной присваивается значение OPTION. В противном случае переменной присваивается значение(?). Этот процесс продолжается до тех пор, пока не будут обработаны все опции. Завершив обработку всех аргументов, команда getopts возвращает ненулевое состояние. Это означает, что все аргументы были переданы.

*****Переменная OPTION содержит значение последнего обработанного аргумента.

Указание значений опций с помощью команды getopts ($OPTARG)

Иногда для сценариев требуется включение фактического, дополнительного значения одной из опций командной строки. Все, что требуется для этого сделать, — поставить двоеточие после буквы опции параметра [строка_параметров]. Например:

getopts ahfvc OPTION — ни одна из опций не требует значений

getopts ahfvc: OPTION — опция "с" требует значения

getopts ahfvc:: OPTION опция "с" требует значения, но может и не иметь значения (аргумента, аргумент в этом случае должен не отделяться пробелом от опции).

После указании значения, оно будет присвоено переменной OPTARG как в примере ниже: c)COPIES=$OPTARG. Если попытаться передать данную опцию без этого значения, отобразится сообщение об ошибке. Стандартное сообщение об ошибке не является особо информативным, поэтому "подавите" его отображение >&2 и выполните следующее: Укажите двоеточие перед параметром 'строка_параметров': while getopts :ahfgvc: OPTION (или не указывайте, в зависимости от версии getopts, если первый символ строки опций (optstring) — двоеточие (:), используется немногословное информирование об ошибках, в примере ниже двоеточие перед параметрами строки пропущено, поэтому getopts выдает сообщение, No arg for -c option ..... При обычной работе выдаются диагностические сообщения, если обнаруживаются недопустимые опции или недостающие аргументы. Двоеточие перед строкой параметров делает возможным использование оператора usage внутри конструкции case. При этом применяется символ \?), экранированный как специальный и выполняющий функции перехвата ошибок.

case

..........

\?) # оператор usage

echo "`basename $0` -[a h f v] -[с value] file">&2

esac

Итого измененный сценарий getopt1:

$ ~ vim getopt1

#/bin/sh

#getopt1

# присвоение значений переменным

ALL=false

HELP=false

FILE=false

VERBOSE=false

COPIES=0 # значение опции -с равно нулю


while getopts ahfgvc: OPTION; do

case $OPTION in

a)ALL=true

echo "ALL is $ALL" ;;

h)HELP=true

echo "HELP is $HELP" ;;

f)FILE=true

echo "FILE is $FILE" ;;

v)VERBOSE=true

echo "VERBOSE is $VERBOSE" ;;

c)COPIES=$OPTARG

echo "COPIES is $COPIES" ;;

\?) # оператор usage, обычно в виде функции или просто:

echo "Usage `basename $0`: -[ahfv] -[c value] file" >&2 ;;

esac

done

При выполнении указанного выше сценария с опцией -c, не содержащей значения, возникает ошибка. В этом случае отображается сообщение оболочки и usage:

$ sh getopt1 -ah -c

ALL is true

HELP is true

No arg for -c option

getopt1 -[ahfv] -[c value] file

$ sh getopt1 -ahfv -c5

ALL is true

HELP is true

FILE is true

VERBOSE is true

COPIES is 5

$ sh getopt1 -?

Usage getopt1: -[ahfv] -[c value] file

$

Доступ к значениям

Команда getopts часто применяется для выполнения сценариев резервирования. Благодаря этому пользователь может указывать различные носители, используемые для резервирования данных. Ниже приводится примерный шаблон сценария, использующего команду getopts.

$ cat > backups

#!/bin/sh

# backups

usage ()

{

echo "Usage: `basename $0` -d[device] -l[logfile]"

exit 1

}

if [ $# = 0 ]; then usage; fi


while getopts d:l: OPTION; do

case $OPTION in

d)DEVICE=$OPTARG; echo yes -$DEVICE ;;

l)LOGFILE=$OPTARG; echo yes -$LOGFILE ;;

\?)usage ;;

esac

done

echo "Вы выбрали следующие параметры: Device:$DEVICE File name:$LOGFILE"

^C

$

В данном сценарии при указании опции d нужно присваивать значение. Это значение представляет собой наименование пути для носителя. Пользователь может также определить, создавать ли резервную копию, если весь вывод направляется в журнальный файл. Выполнение сценария, использующего указанные ниже входные данные, приводит к следующим результатам:

$ sh backups

Usage: backups -d[device] -l[logfile]

$ sh backups -d sda1 -l /var/tmp/logfile

yes -sda1

yes -/var/tmp/logfile

Вы выбрали следующие параметры:

Device:sda1 File name:/var/tmp/logfile

$

После того как команда getopts завершит выполнение проверки, значения, присвоенные OPTARG, могут быть использованы в процессе обычной обработки. Конечно, если в сценарии имеются опции, они должны быть установлены для дальнейшей обработки и проверки значений. Вот и все, что требуется знать о том, каким образом команда getopts обеспечивает передачу параметров командной строки. Для фактической обработки файлов целесообразно использовать цикл for.

Способность обрабатывать опции командной строки придает сценарию профессионализм и сходство с системной командой, внешне нет ни каких отличий, а название этой команды будет название вашего сценария, в контексте "администрирования" весьма удобно иметь набор подобных сценариев-команд с богатым набором опций ......."Easy way to make your script use classic option syntax".

В итоге сравнивая методы getopts и shift, применяемые для обработки опций командной строки, можно выделить отличие которое заключается в использовании методом getopts опции VERBOSE. Переменная VERBOSE имеет значение "nо", заданное по умолчанию, но при перехвате значения опции командной строки с помощью конструкции case переменной VERBOSE присваивается значение "yes". Отображение команд на экране осуществляется с помощью простой конструкции if.

if [ "VERBOSE"="on" ]; then

echo "doing upper on $LOOP..newflie called $LOOP$EXT"

fi

Если применяется оболочка для системных команд, которые всегда отображают результаты своих действий, то вывод, включающий произвольные ошибки, просто перенаправляется в /dev/null. command > /dev/null 2>&1

По умолчанию переменная VERBOSE не установлена (нет отображения). Активизировать эту переменную можно посредством опции -v.

По скольку при указании опций командной строки в сценариях неплохо придерживаться соглашений о наименованиях, принятых в UNIX /Linux. Справа описываются некоторые общие опции и их значения. Зависит от реализации getopts, но если например вы укажете опцию зарезервированную POSIX, getopts может ее и не обработать.

Обобщая:


Для разбора параметров команда getopts используется в рамках цикла while. Типичная конструкция цикла while с getopts несколько отличается от стандартной из-за отсутствия квадратных скобок, проверяющих условие продолжения цикла.

синтаксис: getopts optstring name [arg]

optstring Список символов, которые распознаются в качестве аргументов. Пример: -h, -v (короткие опции).

name Разобранный аргумент из позиционных параметров ($@) будет сохранен в переменной $name (название любое, в примерах выше это OPTION).

Команда getopts использует скрытые переменные: $OPTIND , $OPTARG и $OPTERR

$OPTIND Индекс опции, переменная опции

$OPTARG Дополнительный аргумент опции

$OPTERR Содержит значение 0 или 1, указывающее на необходимость вывода сообщений об ошибках при обработке каждого из параметров (перед обработкой каждого из параметров устанавливается значение 1, поэтому нам придется самостоятельно устанавливать значение 0 для сокрытия сообщений об ошибках (символ двоеточия, первый символ optstring)).

Цикл while используется для итерации по списку переданных аргументов, далее getopts с помощью индекса - OPTIND получит аргумент и сохранит его в переменной $name.

Оператор case используется для проверки совпадения шаблона с $name и запуска соответствующего оператора

Символ двоеточия, следующий за именем опции, указывает на то, что она имеет дополнительный аргумент [arg]. Каждый проход цикла извлекает очередную опцию и ее аргумент (если он есть), обрабатывается, затем уменьшается на 1 (скрытая переменная $OPTIND) и выполняется переход к началу новой итерации.

Опциям, передаваемым в сценарий из командной строки, должен предшествовать символ (-) или (+). Этот префикс (- или +) позволяет getopts отличать опции от прочих аргументов. getopts не будет обрабатывать аргументы, если им не предшествует символ (-) или (+), выделение опций будет прекращено как только встретится первый аргумент.

Метод shift позволит преодолеть ограничение количество параметров ($1...$9), shift $(($OPTIND - 1)) с использованием "Арифметического расширения" (вычисляет арифметическое выражение и подставляет его значение) в итоге shift выполняет смещение среди всех вызываемых аргументов,(переменная $OPTING содержит значение(индекс, номер опции) последнего обработанного аргумента) благодоря чему появляется возможность выполнять дальнейшую обработку.

Если указана недопустимая опция, переменной опции присваивается значение ?, которое можно перехватить и послать пользователю соответствующее сообщение об использовании

(\?) echo "......"), это станет возможным если добавить к списку допустимых параметров знак двоеточия перед параметрами для того чтобы отключить обработку ошибок по умолчанию для недопустимых параметров. Рекомендуется всегда отключать обработку ошибок по умолчанию.


PS: На деле существует getopts это встроенная команда bash и getopt это внешняя утилита

$ type getopts

getopts is a shell builtin

$ type getopt

getopt is hashed (/usr/bin/getopt)

разница между ними очень мутная и простому смертному user-у знать ее не обязательно, если getopts обрабатывает строчные параметры в цикле и присваивает им определенные вами значения, то getopt не делает никакой обработки с последующим присваиванием, getopt "просто" конвертирует наши параметры в стандартный вид (системный сервис) например:

myscript -ab infile.txt -ooutfile.txt

в

myscript -a -b -o outfile.txt infile.txt

однако поддерживает "long-named command-line options", кроме того есть разные версии getopt, базовая getopt и GNU getopt, точнее так:

Bash builtin getopts Это не поддерживает длинные имена опций с префиксом double-dash. Это только поддерживает односимвольные опции.

BSD UNIX реализация standalone getopt (что и использует MacOS). Это тоже не поддерживает длинные опции.

GNU реализация standalone getopt. GNU getopt (используется командой-строкой getopt на Linux) поддерживает разбор длинных опций.


PS: К сожалению как не обобщай все равно выходит "многословно" бороться с этим можно только практикой, и на практике несколько самостоятельных сценариев дадут полное представление про эту чудную утилиту:

Небольшой скрипт для очистки системы "легкая версия":


$ cat cleaner

#!/bin/sh

# cleaner

usage ()

{

echo "Usage: `basename $0` -b -f -d -h [-bfdh]"

echo "-b Удалеие неиспользуемых пакетов из кэша"

echo "-f Очистка кэша утилиты apt"

echo "-d Удаление не нужных зависимостей"

echo "-h Удаление логов"

exit 1

}

if [ $# = 0 ]; then usage; fi


while getopts :bfdh OPTION; do

case $OPTION in

b) echo Удаление неиспользуемых пакетов из кэша:; `apt-get -y autoclean` ;;

f) echo Очистка кэша, утилиты apt:; `apt-get -y clean` ;;

d) echo Удаление ненужных зависимостей:; `apt-get -y autoremove` ;;

h) echo Удаление логов:;

cat /dev/null > /var/log/auth.log

cat /dev/null > /var/log/kern.log

cat /dev/null > /var/log/syslog

cat /dev/null > /var/log/syslog1

cat /dev/null > /var/log/messages

cat /dev/null > /var/log/mail.err

cat /dev/null > /var/log/mail.info

cat /dev/null > /var/log/mail.log

cat /dev/null > /var/log/mail.warn

cat /dev/null > /var/log/user.log

cat /dev/null > /var/log/deamon.log

cat /dev/null > /var/log/fontconfig.log

cat /dev/null > /var/log/auth.log

cat /dev/null > /var/log/boot.log ;;

\?) usage ;;

esac

done


$ chmod +x cleaner

$ cp cleaner /usr/bin

# cleaner

$ ~ getopt --help

Использование:

getopt <optstring> <parameters>

getopt [options] [--] <optstring> <parameters>

getopt [options] -o|--options <optstring> [options] [--] <parameters>

Parse command options.

Параметры:

-a, --alternative allow long options starting with single -

-l, --longoptions <longopts> the long options to be recognized

-n, --name <progname> the name under which errors are reported

-o, --options <optstring> the short options to be recognized

-q, --quiet disable error reporting by getopt(3)

-Q, --quiet-output no normal output

-s, --shell <shell> set quoting conventions to those of <shell>

-T, --test test for getopt(1) version

-u, --unquoted do not quote the output

Для более детальной информации смотрите getopt(1).

$ ~ man getopt

GETOPT(1) User Commands GETOPT(1)

NAME

getopt - parse command options (enhanced)

SYNOPSIS

getopt optstring parameters

getopt [options] [--] optstring parameters

getopt [options] -o|--options optstring [options] [--] parameters

DESCRIPTION

getopt is used to break up (parse) options in command lines for easy parsing by shell proce?

dures, and to check for legal options. It uses the GNU getopt(3) routines to do this.

The parameters getopt is called with can be divided into two parts: options which modify the way

getopt will do the parsing (the options and the optstring in the SYNOPSIS), and the parameters

which are to be parsed (parameters in the SYNOPSIS). The second part will start at the first

non-option parameter that is not an option argument, or after the first occurrence of '--'. If

no '-o' or '--options' option is found in the first part, the first parameter of the second part

is used as the short options string.

If the environment variable GETOPT_COMPATIBLE is set, or if the first parameter is not an option

(does not start with a '-', the first format in the SYNOPSIS), getopt will generate output that

is compatible with that of other versions of getopt(1). It will still do parameter shuffling

and recognize optional arguments (see section COMPATIBILITY for more information).

Traditional implementations of getopt(1) are unable to cope with whitespace and other (shell-

specific) special characters in arguments and non-option parameters. To solve this problem,

this implementation can generate quoted output which must once again be interpreted by the shell

(usually by using the eval command). This has the effect of preserving those characters, but

you must call getopt in a way that is no longer compatible with other versions (the second or

third format in the SYNOPSIS). To determine whether this enhanced version of getopt(1) is

installed, a special test option (-T) can be used.

OPTIONS

-a, --alternative

Allow long options to start with a single '-'.

-h, --help

Display help text and exit. No other output is generated.

.......................

.......................

$ ~ getopts --help getopts: getopts строка_параметров имя [аргумент]

Анализ аргументов параметра. getopts используется процедурами командного процессора для анализа позиционных параметров. «строка_параметров» содержит буквы распознаваемых параметров. Если после буквы идёт двоеточие, считается, что у параметра есть аргумент, который должен быть отделён пробелом. При каждом своём вызове getopts поместит следующий параметр в переменную $имя, проинициализировав это имя, если оно не существует, и проиндексирует следующий обрабатываемый аргумент в переменной $OPTIND. Переменная $OPTIND инициализируется при каждом вызове командного процессора или скрипта. Когда для параметра нужен аргумент, getopts помещает этот аргумент в переменную $OPTARG. getopts сообщает об ошибках двумя способами. Если первый символ в «строке_параметров» является двоеточием, getopts включает режим молчания. В этом режиме сообщения об ошибках не выводятся. Если указан неверный параметр, getopts помещает символ параметра в переменную $OPTARG. Если обязательный аргумент не найден, getopts помещает «:» в «имя» и задаёт для $OPTARG символ найденного параметра. Если getopts не в режиме молчания, и был указан неверный параметр, getopts помещает «?» в НАЗВАНИЕ и удаляет переменную OPTARG. Если обязательный аргумент не найден, в НАЗВАНИЕ помещается «?», переменная OPTARG удаляется и выводится диагностическое сообщение.

Если переменная OPTERR имеет значение 0, getopts отключает вывод сообщений об ошибках, даже если первый символ переменной OPTSTRING не является двоеточием. По умолчанию переменная OPTERR имеет значение 1. Getopts обычно анализирует позиционные параметры ($0–$9), но если

задано больше аргументов, анализируются последние.

Состояние выхода:

Возвращает успех, если найден параметр. Возвращает ошибку, если достигнут конец параметров или возникла ошибка.

$ ~man getopts

GETOPTS(1P) POSIX Programmer's Manual GETOPTS(1P)

PROLOG

This manual page is part of the POSIX Programmer's Manual. The Linux implementation of this

interface may differ (consult the corresponding Linux manual page for details of Linux behav?

ior), or the interface may not be implemented on Linux.

NAME

getopts — parse utility options

SYNOPSIS

getopts optstring name [arg...]

DESCRIPTION

The getopts utility shall retrieve options and option-arguments from a list of parameters. It

shall support the Utility Syntax Guidelines 3 to 10, inclusive, described in the Base Defini?

tions volume of POSIX.1?2008, Section 12.2, Utility Syntax Guidelines.

Each time it is invoked, the getopts utility shall place the value of the next option in the

shell variable specified by the name operand and the index of the next argument to be processed

in the shell variable OPTIND. Whenever the shell is invoked, OPTIND shall be initialized to 1.

When the option requires an option-argument, the getopts utility shall place it in the shell

variable OPTARG. If no option was found, or if the option that was found does not have an

option-argument, OPTARG shall be unset.

If an option character not contained in the optstring operand is found where an option character

is expected, the shell variable specified by name shall be set to the <question-mark> ('?')

character. In this case, if the first character in optstring is a <colon> (':'), the shell vari?

able OPTARG shall be set to the option character found, but no output shall be written to stan?

dard error; otherwise, the shell variable OPTARG shall be unset and a diagnostic message shall

be written to standard error. This condition shall be considered to be an error detected in the

way arguments were presented to the invoking application, but shall not be an error in getopts

processing.

If an option-argument is missing:

* If the first character of optstring is a <colon>, the shell variable specified by name shall

be set to the <colon> character and the shell variable OPTARG shall be set to the option

character found.