Как использовать getopts для анализа параметров сценария оболочки Linux
Опубликовано: 2022-06-25 Вы хотите, чтобы ваши сценарии оболочки Linux более изящно обрабатывали параметры и аргументы командной строки? Встроенная команда Bash getopts
позволяет с легкостью анализировать параметры командной строки. Мы покажем вам, как это сделать.
Представляем встроенную функцию getopts
Передача значений в сценарий Bash довольно проста. Вы вызываете свой сценарий из командной строки или из другого сценария и предоставляете список значений за именем сценария. Доступ к этим значениям можно получить внутри вашего скрипта как к переменным, начиная с $1
для первой переменной, $2
для второй и так далее.
Но если вы хотите передать параметры сценарию, ситуация быстро усложняется. Когда мы говорим об опциях, мы имеем в виду опции, флаги или переключатели, которые могут обрабатывать такие программы, как ls
. Им предшествует тире « -
», и они обычно служат для программы индикатором включения или выключения некоторых аспектов ее функций.
Команда ls
имеет более 50 параметров, в основном связанных с форматированием вывода. Опция -X
(сортировка по расширению) сортирует выходные данные в алфавитном порядке по расширению файла. Параметр -U
(несортированный) приводит список в порядке каталога.
Опции — это то, что они необязательны. Вы не знаете, какие параметры (если они есть) выберет пользователь, и вы также не знаете, в каком порядке они могут перечислить их в командной строке. Это увеличивает сложность кода, необходимого для анализа параметров.
Все становится еще сложнее, если некоторые из ваших параметров принимают аргумент, известный как аргумент параметра . Например, ожидается, что за параметром ls -w
(width) следует число, представляющее максимальную ширину отображения вывода. И, конечно же, вы можете передавать в свой скрипт другие параметры, которые являются просто значениями данных, которые вообще не являются параметрами.
К счастью, getopts
справляется с этой сложностью за вас. А поскольку это встроенная функция, она доступна во всех системах с оболочкой Bash, поэтому устанавливать ее нечего.
Примечание: getopts Не getopt
Есть более старая утилита под названием getopt
. Это небольшая служебная программа , а не встроенная. Существует много разных версий getopt
с различным поведением, тогда как встроенная getops
следует рекомендациям POSIX.
тип getopts
введите getopt
Поскольку getopt
не является встроенной функцией, она не обладает некоторыми автоматическими преимуществами, которые дает getopts
, например разумной обработкой пробелов. С помощью getopts
оболочка Bash запускает ваш сценарий, а оболочка Bash выполняет синтаксический анализ параметров. Вам не нужно вызывать внешнюю программу для обработки синтаксического анализа.
Компромисс заключается в том, что getopts
не обрабатывает длинноформатные имена опций с двойным дефисом. Таким образом, вы можете использовать параметры, отформатированные как -w
, но не « ---wide-format
». С другой стороны, если у вас есть сценарий, который принимает параметры -a
, -b
и
, -c
getopts
позволяет вам комбинировать их, например -abc
, -bca
или -bac
и так далее.
В этой статье мы обсуждаем и демонстрируем getopts
, поэтому не забудьте добавить последнюю букву «s» к имени команды.
СВЯЗАННЫЕ С: Как экранировать пробелы в путях к файлам в командной строке Windows
Краткий обзор: обработка значений параметров
Этот скрипт не использует пунктирные опции, такие как -a
или -b
. Он принимает «обычные» параметры в командной строке, и доступ к ним внутри скрипта осуществляется как к значениям.
#!/бин/баш # получить переменные одну за другой echo "Переменная 1: $1" echo "Вторая переменная: $2" echo "Переменная 3: $3" # цикл по переменным для var в " $@" сделать эхо "$ вар" Выполнено
Доступ к параметрам внутри скрипта осуществляется как к переменным $1
, $2
или $3
.
Скопируйте этот текст в редактор и сохраните его как файл с именем «variables.sh». Нам нужно сделать его исполняемым с помощью команды chmod
. Вам нужно будет выполнить этот шаг для всех сценариев, которые мы обсуждаем. Просто каждый раз подставляйте имя соответствующего файла скрипта.
chmod +x переменные.sh
Если мы запустим наш скрипт без параметров, мы получим этот вывод.
./переменные.sh
Мы не передали никаких параметров, поэтому у скрипта нет значений для отчета. На этот раз давайте укажем некоторые параметры.
./variables.sh как гикать
Как и ожидалось, переменные $1
, $2
и $3
были установлены в значения параметров, и мы видим их напечатанными.
Этот тип обработки параметров «один к одному» означает, что нам нужно заранее знать, сколько будет параметров. Цикл внизу скрипта не заботится о количестве параметров, он всегда перебирает их все.
Если мы предоставляем четвертый параметр, он не присваивается переменной, но цикл по-прежнему обрабатывает его.
./variables.sh как сделать веб-сайт гика
Если мы поместим два слова в кавычки, они будут рассматриваться как один параметр.
./variables.sh как "поумнеть"
Если нам потребуется, чтобы наш сценарий обрабатывал все комбинации параметров, параметров с аргументами и «обычных» параметров типа данных, нам потребуется отделить параметры от обычных параметров. Мы можем добиться этого, поместив все параметры — с аргументами или без них — перед обычными параметрами.
Но не будем бежать, пока не научимся ходить. Давайте рассмотрим простейший случай обработки параметров командной строки.
Варианты обработки
Мы используем getopts
в цикле while
. Каждая итерация цикла работает с одной опцией, которая была передана сценарию. В каждом случае переменная OPTION
устанавливается на опцию, идентифицированную getopts
.
С каждой итерацией цикла getopts
переходит к следующей опции. Когда опций больше нет, getopts
возвращает false
и цикл while
завершается.
Переменная OPTION
сопоставляется с шаблонами в каждом из предложений оператора case. Поскольку мы используем оператор case, не имеет значения, в каком порядке параметры указываются в командной строке. Каждый параметр помещается в оператор case, и запускается соответствующее предложение.
Отдельные предложения в операторе case упрощают выполнение определенных действий в сценарии. Как правило, в реальном сценарии вы устанавливаете переменную в каждом предложении, и они будут действовать как флаги дальше в сценарии, разрешая или запрещая некоторые функции.
Скопируйте этот текст в редактор и сохраните его как скрипт с именем «options.sh» и сделайте его исполняемым.
#!/бин/баш в то время как getopts 'abc' ОПЦИЯ; делать case "$OPTION" в а) echo "Опция a используется" ;; б) echo "Используется вариант b" ;; в) echo "Используется вариант c" ;; ?) echo "Использование: $(базовое имя $0) [-a] [-b] [-c]" выход 1 ;; эсак Выполнено
Это строка, определяющая цикл while.
в то время как getopts 'abc' ОПЦИЯ; делать
За командой getopts
следует строка параметров . Здесь перечислены буквы, которые мы собираемся использовать в качестве опций. В качестве опций можно использовать только буквы из этого списка. Так что в этом случае -d
будет недействительным. Это будет захвачено предложением ?)
, потому что getopts
возвращает вопросительный знак « ?
” для неопознанного варианта. Если это произойдет, правильное использование будет напечатано в окне терминала:
echo "Использование: $(базовое имя $0) [-a] [-b] [-c]"
По соглашению заключение параметра в скобки « []
» в этом типе сообщения о правильном использовании означает, что параметр является необязательным. Команда basename удаляет все пути к каталогам из имени файла. Имя файла сценария хранится в $0
в сценариях Bash.
Давайте использовать этот скрипт с различными комбинациями командной строки.
./options.sh -а
./options.sh -a -b -c
./options.sh -ab -c
./options.sh -cab
Как мы видим, все наши тестовые комбинации параметров анализируются и обрабатываются правильно. Что, если мы попробуем вариант, которого не существует?
./options.sh -d
Предложение об использовании срабатывает, что хорошо, но мы также получаем сообщение об ошибке от оболочки. Это может или не может иметь значение для вашего варианта использования. Если вы вызываете сценарий из другого сценария, который должен анализировать сообщения об ошибках, это усложнит задачу, если оболочка также генерирует сообщения об ошибках.
Отключить сообщения об ошибках оболочки очень просто. Все, что нам нужно сделать, это поставить двоеточие « :
» в качестве первого символа строки параметров.
Либо отредактируйте файл «options.sh» и добавьте двоеточие в качестве первого символа строки параметров, либо сохраните этот скрипт как «options2.sh» и сделайте его исполняемым.
#!/бин/баш в то время как getopts ':abc' ОПЦИЯ; делать case "$OPTION" в а) echo "Вариант a используется" ;; б) echo "Используется вариант b" ;; в) echo "Используется вариант c" ;; ?) echo "Использование: $(базовое имя $0) [-a] [-b] [-c]" выход 1 ;; эсак Выполнено
Когда мы запускаем это и генерируем ошибку, мы получаем наши собственные сообщения об ошибках без каких-либо сообщений оболочки.
./options2.sh.sh -d
Использование getopts с опционными аргументами
Чтобы сообщить getopts
, что за параметром будет следовать аргумент, поставьте двоеточие « :
» сразу после буквы параметра в строке параметров.
Если после «b» и «c» в нашей строке параметров поставить двоеточие, getopt
будет ожидать аргументы для этих параметров. Скопируйте этот скрипт в свой редактор и сохраните его как «arguments.sh» и сделайте его исполняемым.
Помните, что первое двоеточие в строке параметров используется для подавления сообщений об ошибках оболочки — оно не имеет ничего общего с обработкой аргументов.
Когда getopt
обрабатывает параметр с аргументом, этот аргумент помещается в переменную OPTARG
. Если вы хотите использовать это значение в другом месте вашего скрипта, вам нужно будет скопировать его в другую переменную.
#!/бин/баш в то время как getopts ':ab:c:' OPTION; делать case "$OPTION" в а) echo "Вариант a используется" ;; б) argB="$OPTARG" echo "Опция b используется с: $argB" ;; в) argC="$OPTARG" echo "Опция c используется с: $argC" ;; ?) echo "Использование: $(базовое имя $0) [-a] [-b аргумент] [-c аргумент]" выход 1 ;; эсак Выполнено
Давайте запустим это и посмотрим, как это работает.
./arguments.sh -a -b "как гик" -c обзорщик
./arguments.sh -c обзорщик -a
Итак, теперь мы можем обрабатывать параметры с аргументами или без них, независимо от порядка, в котором они заданы в командной строке.
А как же обычные параметры? Ранее мы говорили, что знали, что нам придется помещать их в командную строку после любых опций. Посмотрим, что произойдет, если мы это сделаем.
Варианты и параметры микширования
Мы изменим наш предыдущий сценарий, включив в него еще одну строку. Когда цикл while
завершится и все параметры будут обработаны, мы попытаемся получить доступ к обычным параметрам. Мы выведем значение в $1
.
Сохраните этот скрипт как «arguments2.sh» и сделайте его исполняемым.
#!/бин/баш в то время как getopts ':ab:c:' OPTION; делать case "$OPTION" в а) echo "Вариант a используется" ;; б) argB="$OPTARG" echo "Опция b используется с: $argB" ;; в) argC="$OPTARG" echo "Опция c используется с: $argC" ;; ?) echo "Использование: $(базовое имя $0) [-a] [-b аргумент] [-c аргумент]" выход 1 ;; эсак Выполнено echo "Первая переменная: $1"
Теперь попробуем несколько комбинаций опций и параметров.
./arguments2.sh Дэйв
./arguments2.sh - дейв
./arguments2.sh -a -c дэйв как компьютерщик
Итак, теперь мы видим проблему. Как только какие-либо параметры используются, переменные $1
и далее заполняются флагами параметров и их аргументами. В последнем примере $4
будет содержать значение параметра «dave», но как получить к нему доступ в сценарии, если вы не знаете, сколько опций и аргументов будет использоваться?
Ответ заключается в использовании OPTIND
и команды shift
.
Команда shift
отбрасывает первый параметр — независимо от типа — из списка параметров. Другие параметры «перетасовываются», поэтому параметр 2 становится параметром 1, параметр 3 становится параметром 2 и так далее. Итак, $2
становится $1
, $3
становится $2
и так далее.
Если вы укажете shift
с числом, это удалит столько параметров из списка.
OPTIND
подсчитывает параметры и аргументы по мере их обнаружения и обработки. Как только все опции и аргументы будут обработаны, OPTIND
будет на единицу больше, чем количество опций. Поэтому, если мы используем shift для обрезки параметров (OPTIND-1)
из списка параметров, у нас останутся обычные параметры в $1
и выше.
Это именно то, что делает этот скрипт. Сохраните этот скрипт как «arguments3.sh» и сделайте его исполняемым.
#!/бин/баш в то время как getopts ':ab:c:' OPTION; делать case "$OPTION" в а) echo "Вариант a используется" ;; б) argB="$OPTARG" echo "Опция b используется с: $argB" ;; в) argC="$OPTARG" echo "Опция c используется с: $argC" ;; ?) echo "Использование: $(базовое имя $0) [-a] [-b аргумент] [-c аргумент]" выход 1 ;; эсак Выполнено echo "До - первая переменная: $1" сдвиг "$(($OPTIND -1))" echo "После - первая переменная: $1" echo "Остальные аргументы (операнды)" для x в "$@" делать эхо $х Выполнено
Мы запустим это с сочетанием опций, аргументов и параметров.
./arguments3.sh -a -c как гик "дэйв ди" дози клювовидный мик тик
Мы можем видеть, что до того, как мы вызвали shift
, $1
содержал «-a», но после команды сдвига $1
содержит наш первый параметр без опций и аргументов. Мы можем перебирать все параметры так же легко, как и в скрипте без анализа параметров.
Всегда хорошо иметь варианты
Обработка опций и их аргументов в сценариях не должна быть сложной. С помощью getopts
вы можете создавать скрипты, которые обрабатывают параметры, аргументы и параметры командной строки точно так же, как это должны делать собственные скрипты, совместимые с POSIX.