Я запутался, как включить необязательные аргументы / флаги при написании сценария bash для следующей программы:
Программа требует двух аргументов:
run_program --flag1 <value> --flag2 <value>
Однако есть несколько необязательных флагов:
run_program --flag1 <value> --flag2 <value> --optflag1 <value> --optflag2 <value> --optflag3 <value> --optflag4 <value> --optflag5 <value>
Я хотел бы запустить скрипт bash таким образом, чтобы он принимал пользовательские аргументы. Если пользователи вводят только два аргумента в порядке, то это будет:
#!/bin/sh
run_program --flag1 $1 --flag2 $2
Но что, если какие-либо необязательные аргументы включены? Я думаю, что это будет
if [ --optflag1 "$3" ]; then
run_program --flag1 $1 --flag2 $2 --optflag1 $3
fi
Но что, если дается 4 доллара, а не 3?
shell-script
arguments
ShanZhengYang
источник
источник
getopts
это то, что вы хотите. Без этого вы можете использовать цикл с оператором switch для определения каждого флага, необязательного или нет.getopts
, мне нужно будет указать каждую комбинацию аргументов? 3 и 4, 3 и 5, 3 и 4 и 5 и т. Д.?getopts
. Допустим, я заставляю пользователей запускать скрипт со всеми аргументами:run_program.sh VAL VAL FALSE FALSE FALSE FALSE FALSE
который запускает программу какprogram --flag1 VAL --flag2 VAL
. Если вы запустилиrun_program.sh VAL VAL FALSE 10 FALSE FALSE FALSE
, программа запустится какprogram --flag1 VAL --flag2 VAL --optflag2 10
. Как вы можете получить такое поведение сgetopts
?Ответы:
В этой статье показаны два разных способа -
shift
иgetopts
(и обсуждаются преимущества и недостатки двух подходов).С
shift
вашим сценарием смотрит$1
, решает, какое действие предпринять, а затем выполняетshift
, перемещается$2
в$1
,$3
в$2
и т. Д.Например:
При этом
getopts
вы определяете (короткие) опции вwhile
выражении:Очевидно, что это всего лишь фрагменты кода, и я пропустил проверку - проверку, что установлены обязательные аргументы flag1 и flag2, и т. Д.
Какой подход вы используете, в некоторой степени зависит от вкуса: насколько вы хотите, чтобы ваш сценарий был переносимым, можете ли вы жить только с короткими (POSIX) опциями или хотите длинные (GNU) опции и т. Д.
источник
while (( $# ))
вместо этогоwhile :;
и часто ухожу с ошибкой в*
случаеset -o nounset
первого решения произойдет ошибка, если не указан параметр. Исправление:case ${1:-} in
использовать массив.
это будет обрабатывать аргументы с пробелами в них правильно.
[править] Я использовал примерно эквивалентный синтаксис,
args=( "${args[@]}" --optflag1 "$3" )
но G-Man предложил лучший способ.источник
args+=( --optflag1 "$3" )
. Возможно, вы захотите увидеть мой ответ на нашу справочную работу « Последствия для безопасности: невозможность заключить в кавычки переменную в оболочках bash / POSIX» , где я обсуждаю этот метод (построения командной строки в массиве путем условного добавления необязательных аргументов).[@]
что у меня есть достаточный инструмент для решения моей проблемы.В сценарии оболочки аргументы: «$ 1», «$ 2», «$ 3» и т. Д. Число аргументов - $ #.
Если ваш сценарий не распознает параметры, вы можете опустить обнаружение параметров и рассматривать все аргументы как операнды.
Для распознавания опций используйте встроенную функцию getopts
источник
Если ваши параметры ввода являются позиционными (вы знаете, в каких местах они находятся) и не указаны с флагами, тогда вам нужно просто создать командную строку. Просто подготовьте аргументы команды для всех них:
Если параметры не указаны, то соответствующие строки пусты и расширяются в ничто. Обратите внимание, что в последней строке нет кавычек. Это потому, что вы хотите, чтобы оболочка разбивала параметры на слова (для предоставления
--flag1
и в$1
качестве отдельных аргументов для вашей программы). Конечно, это пойдет не так, если ваши исходные параметры содержат пробелы. Если вы выполняете это, вы можете оставить его, но если это общий сценарий, он может иметь неожиданное поведение, если пользователь вводит что-то с пробелами. Чтобы справиться с этим, вам нужно сделать код немного страшнее.x
Префикс в[]
тесте есть в случае ,$3
или$4
пусто. В этом случае, баш будет расширяться[ FALSE != $3 ]
в[ FALSE != ]
котором ошибка синтаксиса, так что еще один произвольный символ есть , чтобы защититься от этого. Это очень распространенный способ, вы увидите это во многих сценариях.Я установил
OPTFLAG1
и остальные из них""
в начале, чтобы быть уверенным (в случае, если они были установлены на что-то раньше), но если они не были фактически объявлены в среде, то вам не нужно делать это строго.Пара дополнительных замечаний:
runprogram
и с флагами. Вот о чемJohn N
идет речь. Вот гдеgetopts
становится полезным.-
) для обозначения пустого значения или просто передать пустую строку, например""
, если это не является допустимым значением параметра. Пустая строка также делает тест короче, просто используйтеif [ -n "$3" ]
.""
пустые параметры, как предложено выше, вы все равно можете пропустить все завершающие пустые области.Этот метод в значительной степени используется для передачи параметров компиляторам в Makefiles.
И снова - если входные данные могут содержать пробелы, это становится ужасно.
источник