Скажем, у меня есть скрипт, который вызывается с этой строкой:
./myscript -vfd ./foo/bar/someFile -o /fizz/someOtherFile
или этот:
./myscript -v -f -d -o /fizz/someOtherFile ./foo/bar/someFile
Что общепринятый способ разбора это таким образом, что в каждом конкретном случае (или некоторая комбинация из двух) $v
, $f
и $d
все будет установлен true
и $outFile
будет равно /fizz/someOtherFile
?
zparseopts -D -E -M -- d=debug -debug=d
И иметь и то-d
и другое--debug
в$debug
массиве,echo $+debug[1]
будет возвращать 0 или 1, если используется один из них. Ссылка: zsh.org/mla/users/2011/msg00350.htmlОтветы:
Способ № 1: Использование bash без getopt [s]
Два распространенных способа передачи аргументов пары ключ-значение:
Разделенный пробелами (например,
--option argument
) (без getopt [s])Применение
demo-space-separated.sh -e conf -s /etc -l /usr/lib /etc/hosts
вывод от копирования-вставки блока выше:
Разделенный Bash Равным (например,
--option=argument
) (без getopt [s])Применение
demo-equals-separated.sh -e=conf -s=/etc -l=/usr/lib /etc/hosts
вывод от копирования-вставки блока выше:
Чтобы лучше понять,
${i#*=}
ищите «Удаление подстроки» в этом руководстве . Это функционально эквивалентно`sed 's/[^=]*=//' <<< "$i"`
который вызывает излишний подпроцесс или`echo "$i" | sed 's/[^=]*=//'`
который вызывает два ненужных подпроцессы.Способ № 2: Использование bash с getopt [s]
от: http://mywiki.wooledge.org/BashFAQ/035#getopts
Ограничения getopt (1) (более старые, относительно недавние
getopt
версии):Более поздние
getopt
версии не имеют этих ограничений.Кроме того, есть оболочка POSIX (и другие),
getopts
которая не имеет этих ограничений. Я включил упрощенныйgetopts
пример.Применение
demo-getopts.sh -vf /etc/hosts foo bar
вывод от копирования-вставки блока выше:
Преимущества
getopts
:dash
.-vf filename
в обычном Unix-режиме, автоматически.Недостатком
getopts
является то, что он может обрабатывать только короткие опции (но-h
не--help
) без дополнительного кода.Существует учебник getopts, который объясняет, что означает весь синтаксис и переменные. В bash также есть информация
help getopts
, которая может быть информативной.источник
getopt
которая включает в себя все функциональные возможности,getopts
а затем и некоторые.man getopt
в Ubuntu 13.04 выводитсяgetopt - parse command options (enhanced)
как имя, поэтому я полагаю, что эта расширенная версия является стандартной.getopt
не утилита GNU, она частьutil-linux
.-gt 0
, удалите вашshift
послеesac
, увеличьте все наshift
1 и добавьте этот случай:*) break;;
вы можете обрабатывать не необязательные аргументы. Пример: pastebin.com/6DJ57HTc–default
. В первом примере я замечаю, что если–default
последний аргумент if , он не обрабатывается (считается не opt), еслиwhile [[ $# -gt 1 ]]
не задан какwhile [[ $# -gt 0 ]]
Нет ответа упоминает расширенный Getopt . И ответ с наибольшим количеством голосов вводит в заблуждение: он либо игнорирует
-vfd
короткие варианты стиля (запрошенные OP), либо опции после позиционных аргументов (также запрошенные OP); и он игнорирует ошибки синтаксического анализа. Вместо:getopt
от util-linux или ранее GNU glibc . 1getopt_long()
функцией C в GNU glibc.getopt
не могут этого сделать)script.sh -o outFile file1 file2 -v
(getopts
не делает этого)=
-стиль длинные параметры:script.sh --outfile=fileOut --infile fileIn
(разрешение обоих длинно, если самостоятельно анализирует)-vfd
(реальная работа, если сам анализирует)-oOutfile
или-vfdoOutfile
getopt --test
→ возвращаемого значения 4.getopt
или встроенные оболочкиgetopts
имеют ограниченное использование.Следующие звонки
все возвращаются
со следующим
myscript
1 расширенный getopt доступен на большинстве «bash-систем», включая Cygwin; в OS X попробуйте brew install gnu-getopt или
sudo port install getopt
2,
exec()
соглашенияPOSIXне имеют надежного способа передачи двоичного NULL в аргументах командной строки; эти байты преждевременно заканчиваютпервую версиюаргумента3, выпущенную в 1997 году или ранее (я отслеживал его только до 1997 года)
источник
getopt
это путь.getopt
том, что его нельзя удобно использовать в сценариях-оболочках, где можно иметь несколько параметров, специфичных для сценария-оболочки, и затем передавать параметры сценария, не являющегося оболочкой, неповрежденному упакованному исполняемому файлу. Допустим, у меня естьgrep
вызываемая оболочка,mygrep
и у меня есть опция,--foo
специфичная дляmygrep
, тогда я не могу сделатьmygrep --foo -A 2
, и я-A 2
передаю автоматическиgrep
; Мне нужно сделатьmygrep --foo -- -A 2
. Вот моя реализация поверх вашего решения.man bash
Более лаконичный способ
script.sh
Применение:
источник
while [[ "$#" > 1 ]]
если я хочу поддержать окончание строки логическим флагом./script.sh --debug dev --uglify fast --verbose
. Пример: gist.github.com/hfossli/4368aa5a577742c3c9f9266ed214aa58./script.sh -d dev -d prod
, приведет кdeploy == 'prod'
. Я использовал это в любом случае: P :): +1:./script.sh -d
, не генерирует ошибку, а просто устанавливает$deploy
пустую строку.от: digitalpeer.com с небольшими изменениями
Применение
myscript.sh -p=my_prefix -s=dirname -l=libname
Чтобы лучше понять,
${i#*=}
ищите «Удаление подстроки» в этом руководстве . Это функционально эквивалентно`sed 's/[^=]*=//' <<< "$i"`
который вызывает излишний подпроцесс или`echo "$i" | sed 's/[^=]*=//'`
который вызывает два ненужных подпроцессы.источник
mount -t tempfs ...
. Вероятно, это можно исправить с помощью чего-то подобного иwhile [ $# -ge 1 ]; do param=$1; shift; case $param in; -p) prefix=$1; shift;;
т. Д.-vfd
комбинированные короткие варианты стиля.getopt()
/getopts()
это хороший вариант. Украдено отсюда :источник
$*
является нарушением использованияgetopt
. (Он содержит аргументы с пробелами.) Смотрите мой ответ для правильного использования.На риск добавления еще одного примера, чтобы проигнорировать, вот моя схема.
-n arg
и--name=arg
Надеюсь, это кому-нибудь пригодится.
источник
*) die "unrecognized argument: $1"
или собрать аргументы в переменную*) args+="$1"; shift 1;;
.shift 2
выдачеshift
дважды вместоshift 2
. Предложил редактировать.Я на 4 года опоздал на этот вопрос, но хочу вернуть. Я использовал предыдущие ответы в качестве отправной точки, чтобы привести в порядок мой старый анализ adhoc param. Затем я переработал следующий код шаблона. Он обрабатывает как длинные, так и короткие параметры, используя = или разделенные пробелом аргументы, а также несколько коротких параметров, сгруппированных вместе. Наконец, он повторно вставляет все непарамальные аргументы обратно в переменные $ 1, $ 2 ... Я надеюсь, что это полезно.
источник
-c1
. И использование=
для отделения коротких опций от их аргументов необычно ...Я сочла нужным написать переносимый синтаксический анализ в сценариях, настолько разочаровывающий, что я написал Argbash - генератор кода FOSS, который может генерировать код синтаксического анализа аргументов для вашего сценария, плюс он имеет несколько приятных особенностей:
https://argbash.io
источник
Мой ответ в значительной степени основан на ответе Бруно Броноски , но я как бы скомбинировал его две чистые реализации bash в одну, которую я использую довольно часто.
Это позволяет вам иметь как разделенные пробелами параметры / значения, так и равные определенные значения.
Таким образом, вы можете запустить свой скрипт, используя:
а также:
и оба должны иметь одинаковый конечный результат.
ПЛЮСЫ:
Позволяет для обоих -arg = значение и -arg значение
Работает с любым именем arg, которое вы можете использовать в bash
Чистая Баш. Нет необходимости изучать / использовать getopt или getopts
МИНУСЫ:
Не могу объединить аргументы
Это единственные плюсы и минусы, которые я могу придумать
источник
Я думаю, что этот достаточно прост в использовании:
Пример вызова:
источник
-a=1
как стиль argc. Я предпочитаю ставить сначала основной вариант - опции, а затем специальные с одинарным интервалом-o option
. Я ищу самый простой-лучший способ чтения argvs../myscript -v -d fail -o /fizz/someOtherFile -f ./foo/bar/someFile
с помощью собственного сценария. -d опция не установлена как d:Расширяя превосходный ответ @guneysus, здесь есть твик, который позволяет пользователю использовать любой синтаксис, который он предпочитает, например
против
То есть, равные могут быть заменены пробелами.
Эта «нечеткая интерпретация» может не понравиться, но если вы создаете сценарии, которые взаимозаменяемы с другими утилитами (как в случае с моей, которая должна работать с ffmpeg), гибкость полезна.
источник
Этот пример показывает, как использовать
getopt
иeval
иHEREDOC
иshift
обрабатывать короткие и длинные параметры с и без требуемого значения, которое следует. Кроме того, инструкция switch / case является краткой и легкой для понимания.Наиболее значимые строки сценария выше:
Коротко, по сути, читабельно и обрабатывает практически все (ИМХО).
Надеюсь, что это помогает кому-то.
источник
Я даю вам функцию,
parse_params
которая будет анализировать параметры из командной строки.--all
равно-all
равноall=all
)Сценарий ниже является рабочей демонстрацией копирования-вставки. Смотрите
show_use
функцию, чтобы понять, как использоватьparse_params
.Ограничения:
-d 1
)--any-param
и-anyparam
эквивалентныeval $(parse_params "$@")
должен использоваться внутри функции bash (она не будет работать в глобальной области видимости)источник
show_use "$@"
EasyOptions не требует разборов:
источник
getopts прекрасно работает, если # 1 у вас установлен и # 2 вы собираетесь запустить его на той же платформе. OSX и Linux (например) ведут себя по-разному в этом отношении.
Вот (не getopts) решение, которое поддерживает флаги equals, non-equals и boolean. Например, вы можете запустить свой скрипт следующим образом:
источник
Вот как я это делаю в функции, чтобы не нарушать одновременное выполнение getopts где-то выше в стеке:
источник
Расширяя ответ @ bruno-bronosky, я добавил «препроцессор» для обработки некоторых распространенных форматов:
--longopt=val
в--longopt val
-xyz
в-x -y -z
--
указание конца флаговисточник
Существует несколько способов анализа аргументов cmdline (например, GNU getopt (непереносимый) против BSD (OSX) getopt против getopts) - все это проблематично. Это решение
=
разделитель-vxf
Примеры: любой из
источник
Я хотел бы предложить мою версию анализа параметров, которая позволяет следующее:
Также позволяет это (может быть нежелательным):
Вы должны решить перед использованием, будет ли = использоваться с опцией или нет. Это делается для того, чтобы код оставался чистым (ish).
источник
Решение, которое сохраняет необработанные аргументы. Демоверсии включены.
Вот мое решение. Он ОЧЕНЬ гибок и, в отличие от других, не требует внешних пакетов и аккуратно обрабатывает оставшиеся аргументы.
Использование это:
./myscript -flag flagvariable -otherflag flagvar2
Все, что вам нужно сделать, это отредактировать строку validflags. Он добавляет дефис и ищет все аргументы. Затем он определяет следующий аргумент как имя флага, например
Основной код (короткая версия, подробный с примерами ниже, также версия с ошибками):
Подробная версия со встроенными демонстрациями эха:
Последний, этот выводит ошибку, если пропущен неверный аргумент.
Плюсы: то, что он делает, он обрабатывает очень хорошо. Он сохраняет неиспользуемые аргументы, которых нет во многих других решениях. Это также позволяет вызывать переменные, не определяясь вручную в скрипте. Это также позволяет предварительно заполнять переменные, если не указан соответствующий аргумент. (См. Подробный пример).
Минусы: Невозможно проанализировать одну сложную строку аргумента, например -xcvf будет обрабатываться как один аргумент. Вы можете легко написать дополнительный код в мой, который добавляет эту функциональность, хотя.
источник
Я хочу представить свой проект: https://github.com/flyingangel/argparser
Просто как тот. Окружение будет заполнено переменными с тем же именем, что и аргументы.
источник
Обратите внимание, что это
getopt(1)
была недолгая ошибка AT & T.getopt был создан в 1984 году, но уже похоронен в 1986 году, потому что он не был действительно применим.
Доказательством того факта, что
getopt
он очень устарел, является то, что вместо этого вgetopt(1)
справочной странице все еще упоминается то , что было добавлено в оболочку Bourne в 1986 году вместе со встроенной оболочкой для обработки аргументов с пробелами внутри."$*"
"$@"
getopts(1)
Кстати: если вы заинтересованы в разборе длинных опций в сценариях оболочки, может быть интересно узнать, что
getopt(3)
реализация из libc (Solaris) иksh93
обе добавили единую реализацию длинных опций, которая поддерживает длинные опции как псевдонимы для коротких опций. Это заставляетksh93
иBourne Shell
реализовывать единый интерфейс для длинных опцийgetopts
.Пример длинных опций, взятых из справочной страницы Bourne Shell:
getopts "f:(file)(input-file)o:(output-file)" OPTX "$@"
показывает, как долго псевдонимы опций могут использоваться как в Bourne Shell, так и в ksh93.
Смотрите справочную страницу недавней Bourne Shell:
http://schillix.sourceforge.net/man/man1/bosh.1.html
и справочную страницу для getopt (3) из OpenSolaris:
http://schillix.sourceforge.net/man/man3c/getopt.3c.html
и, наконец, справочная страница getopt (1) для проверки устаревшего $ *:
http://schillix.sourceforge.net/man/man1/getopt.1.html
источник
Я написал Bash Helper, чтобы написать хороший инструмент Bash
Домашняя страница проекта: https://gitlab.mbedsys.org/mbedsys/bashopts
пример:
окажет помощь:
наслаждаться :)
источник
Вот мой подход - использование регулярных выражений.
-qwerty
-q -w -e
--qwerty
=
предоставлять атрибуты, но атрибуты совпадают, пока не встретите дефис + пробел "разделитель", поэтому в--q=qwe ty
qwe ty
одном атрибуте-o a -op attr ibute --option=att ribu te --op-tion attribute --option att-ribute
действительносценарий:
источник
Предположим , мы создаем скрипт с именем
test_args.sh
следующимПосле того, как мы запустим следующую команду:
Выход будет:
источник
Используйте модуль «Аргументы» из bash-модулей.
Пример:
источник
Смешивание позиционных и флаговых аргументов
--param = arg (равно с разделителями)
Свободно смешивая флаги между позиционными аргументами:
может быть достигнуто с довольно кратким подходом:
--param arg (разделенный пробелом)
Это понятнее обычно работают на жидком не смешивать
--flag=value
и--flag value
стили.Это немного рискованно читать, но все еще действует
Источник
источник
Вот getopts, который выполняет синтаксический анализ с минимальным кодом и позволяет вам определить, что вы хотите извлечь в одном случае, используя eval с подстрокой.
В принципе
eval "local key='val'"
Объявляет переменные как локальные, а не глобальные, как большинство ответов здесь.
Называется как:
$ {K: 3} в основном является подстрокой для удаления первого
---
из ключа.источник
Это также может быть полезно знать, вы можете установить значение и, если кто-то предоставит ввод, переопределить значение по умолчанию этим значением.
myscript.sh -f ./serverlist.txt или просто ./myscript.sh (и он принимает значения по умолчанию)
источник
Другое решение без getopt [s], POSIX, старого стиля Unix
Аналогично решению, опубликованному Бруно Броноским, это здесь без использования
getopt(s)
.Главная особенность моего решения заключается в том, что оно позволяет объединять параметры, как и
tar -xzf foo.tar.gz
в случае с нимиtar -x -z -f foo.tar.gz
. И так же, как вtar
,ps
т. Д., Ведущий дефис необязателен для блока коротких опций (но это можно легко изменить). Также поддерживаются длинные опции (но когда блок начинается с одного, тогда требуются два ведущих дефиса).Код с примерами вариантов
Для примера использования смотрите примеры ниже.
Положение вариантов с аргументами
Для чего бы то ни было, опции с аргументами не являются последними (нужны только длинные опции). Поэтому, например, в
tar
(по крайней мере, в некоторых реализациях)f
параметры должны быть последними, потому что имя файла следует (tar xzf bar.tar.gz
работает, ноtar xfz bar.tar.gz
не работает), но здесь это не так (см. Более поздние примеры).Несколько вариантов с аргументами
В качестве еще одного бонуса параметры опций потребляются в порядке опций параметрами с необходимыми опциями. Просто посмотрите на вывод моего скрипта с помощью командной строки
abc X Y Z
(или-abc X Y Z
):Длинные варианты также объединены
Также вы можете также иметь длинные опции в блоке опций, учитывая, что они встречаются последними в блоке. Таким образом, все следующие командные строки эквивалентны (включая порядок обработки параметров и их аргументов):
-cba Z Y X
cba Z Y X
-cb-aaa-0-args Z Y X
-c-bbb-1-args Z Y X -a
--ccc-2-args Z Y -ba X
c Z Y b X a
-c Z Y -b X -a
--ccc-2-args Z Y --bbb-1-args X --aaa-0-args
Все это приводит к:
Не в этом решении
Необязательные аргументы
Опции с необязательными аргументами должны быть возможны с небольшим количеством работы, например, смотря вперед, есть ли блок без дефиса; тогда пользователю потребуется поставить дефис перед каждым блоком, следующим за блоком, с параметром, имеющим необязательный параметр. Может быть, это слишком сложно, чтобы общаться с пользователем, поэтому в этом случае лучше просто использовать ведущий дефис.
Все становится еще сложнее с несколькими возможными параметрами. Я бы не советовал делать опции, пытаясь быть умными, определяя, может ли аргумент быть для него или нет (например, если опция просто принимает число в качестве необязательного аргумента), потому что это может сломаться в будущем.
Я лично предпочитаю дополнительные опции вместо необязательных аргументов.
Опция аргументов представлена знаком равенства
Как и с необязательными аргументами, я не фанат этого (кстати, есть ли тема для обсуждения плюсов и минусов различных стилей параметров?), Но если вы хотите это, вы, вероятно, можете реализовать это сами, как это было сделано на http: // mywiki.wooledge.org/BashFAQ/035#Manual_loop с оператором
--long-with-arg=?*
case и последующим удалением знака равенства (кстати, это сайт, который говорит, что создание объединения параметров возможно с некоторыми усилиями, но «оставил [это] как упражнение для читателя»). «что заставило меня поверить им на слово, но я начал с нуля).Другие заметки
POSIX-совместимый, работает даже на старых установках Busybox, с которыми мне приходилось иметь дело (например
cut
,head
сgetopts
отсутствующим).источник