Вызов сценария оболочки с параметром -option и параметрами

Мне нужно вызвать сценарий оболочки test.sh следующим образом:

 ./test.sh -run/-rerun username password 

Как проверить, прошли ли они -rerun или -rerun в моем сценарии оболочки?

Общим подходом является использование утилиты getopt для разбивки параметров командной строки, переданных скрипту для легкого разбора. getopt поддерживает как короткие (одиночные символы), так и длинные (несколько символов) варианты с аргументами или без них. Когда вызывается getopt передаются два вида параметров: параметры, которые изменяют способ использования параметров getopt , и параметры вызывающего скрипта, которые должны быть проанализированы.

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

  • -o, --options shortopts Короткий вариант для анализа. Аргумент shortopts для этого параметра представляет собой строку символов, которые должны быть распознаны как короткие. Символу опций с требуемым аргументом следует следовать двоеточие : а опция с необязательным аргументом должна сопровождаться двумя двоеточиями :: . Например, строка shortopts ab:c:: соответствует следующим признанным параметрам -a , -b arg , -c и -c arg . Обратите внимание: если этот параметр не указан, getopt будет обрабатывать первый вариант, который не начинается с - (и не является аргументом параметра) в качестве строки shortopts .

  • -l, --longoptions longopts Длинные варианты для анализа. Можно указать сразу несколько опций, разделяя имена опций запятыми или параметр -l может быть задан более одного раза. Обязательные и необязательные аргументы указываются как с опцией -o с : или :: после имени параметра.

  • -a, --alternative . Обычное соглашение, особенно с программным обеспечением GNU , состоит в том, что длинные варианты добавляются с двумя тире, например, --run . Параметр -a указывает getopt чтобы позволить длинные параметры начинаться с одного символа.

  • -q,--quiet Если getopt встречает непризнанную опцию или отсутствующий требуемый аргумент в параметрах, подлежащих анализу, он печатает сообщение формы getopt: unrecognized option '[option name]' или getopt: option '[option name'] requires an argument stderr , сгенерировать нормальный вывод в stdout и выйти с ненулевым статусом. Параметр -q может использоваться для подавления сообщений об ошибках.

  • -n, --name progname Эта опция может использоваться для указания имени программы, которое будет использоваться getopt при представлении указанных выше ошибок.

Первый параметр без параметра (который не является аргументом параметра или рассматривается как shortopts string, как описано выше) обрабатывается getopt как начало списка параметров, который должен быть проанализирован. Начало этих параметров также можно указать с помощью -- , и в этом случае первый параметр после -- рассматривается как начало списка параметров, подлежащего анализу.

Нормальным выходом getopt является расширенный список признанных опций следующим образом:

  • Короткие варианты, представленные вместе, например -abc , расширяются до отдельных опций, т. -abc -a -b -c .

  • Если -a указывается как опция getopt , длинные параметры, начинающиеся с одной тире, например, -foo , получают префикс с дополнительным тире, т. --foo .

  • Процитированы обязательные и необязательные аргументы для параметров, например -b arg становится -b 'arg' , --foo arg и --foo=arg стать --foo 'arg' .

  • Любые оставшиеся аргументы цитируются и отделяются от опций с помощью.

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

 #!/bin/bash OPTS=`getopt -a -l run -l rerun -- "$0" "$@"` if [ $? != 0 ] # There was an error parsing the options then exit 1 fi eval set -- "$OPTS" while true; do case "$1" in --run) echo "option --run specified"; shift;; --rerun) echo "option --rerun specified"; shift;; --) shift; break;; esac done echo "Args:" for arg # Process remaining arguments do echo $arg done 

Объяснение:

 OPTS=`getopt -a -l run -l rerun -- "$0" "$@"` 

Здесь мы устанавливаем переменную OPTS для вывода вывода вызова getopt . Аргументы, переданные здесь getopt представляют собой встроенные переменные, заданные оболочкой bash в этом примере. $0 содержит имя скрипта, а $@ содержит все аргументы командной строки, переданные в скрипт, индивидуально цитируемые. getopt будет обрабатывать аргументы в соответствии с указанными параметрами. В этом примере getopt будет распознавать длинные опции --run и --rerun без аргументов. Благодаря опции -a getopt также распознает формы -rerun и -rerun . Результатом вызова getopt является расширенный список аргументов. Например, вызов скрипта, такой как test.sh -run username password расширяется оболочкой на вызов getopt -a -l run -l rerun -- "test.sh" "-run" "username" "password" , getopt в свою очередь, выведет расширенные аргументы --run -- 'username' 'password' .


 if [ $? != 0 ] # There was an error parsing the options then exit 1 fi 

Встроенная переменная $? содержит возвращаемое значение последней выполненной команды. Значение, getopt нуля, указывает на то, что getopt обнаружил ошибку.


 eval set -- "$OPTS" 

Это существенно заменит исходные аргументы командной строки, переданные скрипту, с расширенными аргументами, выводимыми getopt .


 while true; do case "$1" in --run) echo "option --run specified"; shift;; --rerun) echo "option --rerun specified"; shift;; --) shift; break;; esac done 

Цикл будет обрабатывать каждый позиционный параметр по очереди, начиная с $1 , первого. После расширения getopt есть всего три случая. В конце обработки каждый случайный shift сдвигает позиционные параметры так, что $2 становится $1 , $3 становится $2 и так далее. В связи с этим позиционный параметр $1 будет содержать новое значение на каждой итерации цикла.

Если обрабатываемый параметр принимает требуемый аргумент, значение аргумента можно получить в выражении case через позиционный параметр $2 . Когда параметр и его аргумент обрабатываются, пост-параметр должен быть сдвинут на 2, чтобы избавиться от опции и аргумента.

Поскольку getopt выводит a -- после распознанных опций, перед оставшимися аргументами -- case указывает конец списка опций и условие завершения цикла while.


 echo "Args:" for arg # Process remaining arguments do echo $arg done 

for arg для for arg in "$@" . Обратите внимание, что после цикла while из-за shift в каждом случае $@ теперь содержит только оставшиеся аргументы -- в выходном getopt .