При разработке приложения я начал задаваться вопросом - как мне создавать аргументы командной строки?
Многие программы используют формулу, как это -argument value
или /argument value
. Решение, которое пришло мне в голову, было argument:value
. Я думал, что это хорошо, потому что без пробелов нет никакого способа, чтобы значения и аргументы могли быть испорчены. Также легко разбить строку на две на первой слева от :
символа.
Мои вопросы:
- Является ли популярная
-argument value
формула лучше чемargument:value
(более читабельна, проще в написании, без ошибок, легче для понимания опытными разработчиками)? - Существуют ли некоторые общеизвестные правила, которым я должен следовать при разработке аргументов командной строки (кроме того, если это работает, то все в порядке)?
Попросил некоторые подробности, я предоставлю это. Однако я думаю, что они не должны влиять на ответы. Вопрос о хороших привычках в целом. Я думаю, что они все одинаковы для всех видов приложений.
Мы работаем над приложением, которое будет использоваться в общественных местах (сенсорные тотемы, столы). Приложения написаны с использованием Qt Quick 5 (C ++, QML, JS). На устройствах будет установлена Windows 8.1 / 10. Мы предоставим интерфейсный интерфейс для управления устройствами. Однако некоторые продвинутые администраторы могут захотеть настроить приложение самостоятельно. Это не очень важно со стороны бизнеса, но, поскольку я согласен с тем, что сказал Килиан Фот, я не хочу, чтобы мое приложение доставляло пользователю боль. Не найдя в интернете то, что я хочу, я спросил здесь.
Для более опытных пользователей Stack Exchange: я хотел, чтобы этот вопрос был общим. Может быть, это относится к сообществу вики (я не знаю, можно ли преобразовать существующий вопрос с ответами). Поскольку я хочу, чтобы этот вопрос не зависел от операционной системы и языка программирования, ответы на него могут стать полезным уроком для других разработчиков.
источник
ls -ltr
чтобы объединить варианты-l
,-t
и-r
. Программы в стиле GNU также обычно допускают варианты на основе слов с двойным дефисом, как--reverse
вместо-r
. Существуют и другие популярные соглашения, такие как-h
показ справки,--
сигнализация об окончании опций, указание-
в качестве имени файла разрешения на чтение из стандартного ввода и т. Д.-argument value
не-argument:value
распространен. Общими являются-a value
,-avalue
и--argument=value
.getopt(s)
), где вы можете.Ответы:
В системах POSIX (например, Linux, MacOSX), по крайней мере, для программ, которые могут быть запущены в терминале оболочки (например, в большинстве из них), я бы рекомендовал использовать соглашения о кодировании GNU (в которых также перечислены общие имена аргументов) и заглянуть в рекомендации утилит POSIX. даже для проприетарного программного обеспечения:
всегда обрабатывать
--version
и--help
(даже/bin/true
принимает их !!). Я проклинаю авторов программного обеспечения, не понимая--help
, я ненавижу их (потому чтоprog --help
это первая команда, которую я пробую в новой программе)! Часто--help
может быть сокращено как-h
Пусть в
--help
сообщении перечисляются все параметры (если у вас их слишком много ... в этом случае перечислите наиболее распространенные и явно ссылаетесь на некоторуюman
страницу или URL) и значения параметров по умолчанию, и, возможно, важные (и специфичные для программы) ) переменные среды. Показать эти списки опций при ошибке аргумента опции.принять
-a
короткий аргумент (одна буква) и иметь некоторый эквивалент--long-argument
, поэтому-a2
--long-argument=2
,--long-argument 2
; конечно, вы можете иметь (для редко используемых опций) какое-то--only-long-argument
имя; поскольку модальные аргументы без дополнительных опций-cf
обычно обрабатываются как-c -f
и т. д., так что ваше-argument:value
предложение странное, и я не рекомендую этого делать.используйте GLIBC getopt_long или лучше (например, argp_parse , в OCaml это
Arg
модуль , ...)часто используется
-
для стандартного ввода или вывода (если вы не можете этого сделать, работайте/dev/stdin
и/dev/stdout
даже в тех операционных системах, где их нет)подражать поведению подобных программ путем повторного использования большинства их соглашений об опциях; в частности
-n
для пробежек (а-ляmake
),-h
для помощи,-v
для многословия и т. д ...использовать в
--
качестве разделителя между параметрами и файлом или другими аргументамиесли ваша программа использует
isatty
для проверки, чем stdin является терминалом (и в этом случае ведет себя «интерактивно»), предоставьте опцию принудительного включения неинтерактивного режима, аналогично, если ваша программа имеет интерфейс с графическим интерфейсом (и тестируетgetenv("DISPLAY")
на рабочем столе X11), но может также использоваться в пакетной или командной строке.Некоторые программы (например
gcc
) принимают списки косвенных аргументов, поэтому@somefile.txt
имеет смысл читать аргументы программы изsomefile.txt
; это может быть полезно, когда ваша программа может принимать очень много аргументов (больше, чем ваше ядроARG_MAX
)Кстати, вы могли бы даже добавить некоторые функции автозаполнения для вашей программы и обычных оболочек (например,
bash
илиzsh
)Некоторые старые команды Unix (например
dd
, или дажеsed
) имеют странные командные аргументы для исторической совместимости. Я бы порекомендовал не следовать их вредным привычкам (если только вы не делаете из них лучший вариант).Если ваше программное обеспечение представляет собой ряд взаимосвязанных программ командной строки, черпает вдохновение из мерзавца (который вы , конечно , использовать в качестве инструмента развития), который принимает
git help
иgit --help
и есть многоgit
subcommand
иgit
subcommand
--help
В редких случаях вы также можете использовать
argv[0]
(используя символические ссылки в вашей программе), например,bash
вызывается какrbash
имеет другое поведение ( ограниченная оболочка). Но я обычно не рекомендую делать это; Это может иметь смысл, если ваша программа может использоваться как интерпретатор сценариев с использованием shebang, т.е.#!
в первой строке, интерпретируемой execve (2) . Если вы делаете такие трюки, обязательно документируйте их, в том числе в--help
сообщениях.Помните , что на POSIX оболочка является подстановкой аргументов ( перед тем запуском программы!), Поэтому не требуют символов (например ,
*
или$
или~
) в вариантах , которые должны были бы быть скорлупой маскирования.В некоторых случаях вы можете встроить интерпретатор, такой как GNU guile или Lua, в свое программное обеспечение (не изобретайте свой собственный язык сценариев, полный Turing, если вы не разбираетесь в языках программирования). Это имеет глубокие последствия для дизайна вашего программного обеспечения (так что об этом следует думать заранее!). После этого вы легко сможете передать некоторый сценарий или выражение этому интерпретатору. Если вы выберете такой интересный подход, тщательно продумайте свое программное обеспечение и его интерпретируемые примитивы; у вас может быть какой-то странный пользователь, кодирующий большие сценарии для вашей вещи.
В других случаях вы можете позволить своим опытным пользователям загружать свои плагины в ваше программное обеспечение (используя методы динамической загрузки à la
dlopen
&dlsym
). Опять же, это очень важное проектное решение (поэтому определите и задокументируйте интерфейс плагина с осторожностью), и вам нужно будет определить соглашение для передачи параметров программы этим плагинам.Если ваша программа сложная вещь, сделайте так, чтобы она принимала некоторые файлы конфигурации (в дополнение или замену аргументов программы) и, возможно, имела какой-то способ проверить (или просто проанализировать) эти файлы конфигурации, не запуская весь код. Например, агент пересылки почты (например, Exim или Postfix) довольно сложен, и полезно иметь возможность «полусухого» его запуска (например, наблюдая, как он обрабатывает некоторый заданный адрес электронной почты без фактической отправки электронной почты).
Обратите внимание, что
/option
это Windows или VMS. Это было бы безумием в системах POSIX (потому что файловая иерархия использует/
в качестве разделителя каталогов, а оболочка выполняет глобализацию). Весь мой ответ в основном для Linux (и POSIX).PS Если возможно, сделайте вашу программу свободным программным обеспечением , вы получите улучшения от некоторых пользователей и разработчиков (и добавление новой опции программы часто является одной из самых простых вещей, которую можно добавить к существующему бесплатному программному обеспечению). Кроме того , ваш вопрос зависит много от предполагаемой аудитории : игра для подростков или браузер для бабушки , вероятно , не нужен такой же вид и количество опций , чем компилятор, или сетевой инспектор для центров обработки данных , сисадминов, или программное обеспечение САПР для микропроцессора архитекторы или для мостовых дизайнеров. Инженеру, знакомому с программированием и сценариями, вероятно, больше нравится иметь много настраиваемых параметров, чем у вашей бабушки, и, возможно, он захочет запустить ваше приложение без X11 (возможно, на
crontab
работе).источник
git
это лучший пример. Я не буду рекомендовать даже глядя вcvs
в 2016 годуdd -h
.--help
как правило, поддерживают, но часто не распознают,-h
что раздражает. Я обычно набираю -h, когда забываю опцию в программе, раздражает необходимость повторного ввода команды с более длинной опцией--help
. В конце концов, я напечатал -h, потому что я что-то забыл. Почему пользователь должен помнить, какие программы требуют «--help», а какие программы требуют «-h» для отображения экрана справки? Просто включите опцию для -h и --help.Тот факт, что соглашение о формате данных является популярным, является его преимуществом.
Вы можете легко увидеть, что использование = или: или даже '' в качестве разделителя - это тривиальные различия, которые могут быть преобразованы в друг друга с помощью компьютера без особых усилий. Что было бы большим усилием для человека, чтобы вспомнить: «Теперь, видите, эта редко используемая программа разграничивает вещи с
:
или с=
? Хммм ...»Другими словами, ради любви к Богу, не отклоняйтесь от чрезвычайно укоренившихся соглашений без веской причины. Люди будут помнить вашу программу как «ту, у которой странный и раздражающий синтаксис cmdline» вместо «той, которая спасла мое эссе из колледжа».
источник
dd
используетkey=value
синтаксис. Причиной такого конструктивного решения является то, что этот инструмент (псевдоним: d ata d estroyer) может нанести большой ущерб при неправильном использовании. Заставляя пользователя отказаться от привычной привычки, он заставляет его задуматься о том, что он делает.dd
? Я считаю, что он просто был закодирован в то время (1970-е годы?), Когда ядро ARG_MAX было маленьким, оболочки не имели автозаполнения и--long-arguments
не существовали. С тех пор лучшеdd
оставаться обратно совместимымdd
произошел от другой ОС (кроме UNIX) - языка сценариев (JCL) в IBM OS / 360 - где соглашения были иными, прежде чем были перенесены более или менее неизменными в UNIX - отчасти потому, что те, кто мог его использовать, знали об этом из предыдущая система.С точки зрения непрофессионала
Когда в Риме, делай, как римляне.
-p value
или--parameter value
. В Linux есть инструменты для простого анализа таких параметров и флагов.Я обычно делаю что-то вроде этого:
Если ваше приложение CLI предназначено для Windows, тогда используйте
/flag
и/flag:value
условные обозначения.Некоторые приложения, такие как Oracle, не используют ни того, ни другого. Утилиты Oracle используют
PARAMETER=VALUE
.Одна вещь, которую мне нравится делать, - это, помимо принятия параметров в командной строке, предоставить возможность использования parfile , который является файлом пары ключ-значение, чтобы избежать длинных цепочек параметров. Для этого вы должны предоставить дополнительный
--parfile mifile.par
параметр. Очевидно, что если--parfile
используется, все остальные параметры отбрасываются в пользу того, что находится внутри файла.Дополнительным предложением является возможность использования некоторых пользовательских переменных среды , например, установка переменной среды
MYAPP_WRKSPACE=/tmp
сделает ненужным постоянную установку--wrkspace /tmp
.TAB
а затем оболочка завершит его для них.источник
gcc
) обрабатывают@mifile.par
как ваши--parfile mifile.par
предложения.fooCmd -opt1 -opt2 $(cat more_options.opts)
. Поэтому я ожидаю, что опция «параметр файла конфигурации», если она предусмотрена, должна работать в основном таким же образом.Одна вещь, которая еще не подошла:
Попробуйте разработать свое программное обеспечение от аргументов командной строки вверх. Смысл:
Прежде чем разрабатывать функциональность, разработайте пользовательский интерфейс.
Это позволит вам детально изучить крайние случаи и общие случаи на ранней стадии. Конечно, вы все равно будете абстрагировать внешнее и внутреннее, но это даст гораздо лучший результат, чем просто написание всего кода и затем добавление к нему CLI.
Кроме того, проверьте docopt ( http://docopt.org/ ).
docopt очень помогает во многих языках, особенно для python, где у вас есть строго ограниченные парсеры неблагоприятных для пользователя аргументов, такие как argparse, которые по-прежнему рассматриваются как «ОК». Вместо парсеров, подпарасеров и условных диктов, вы просто определяете синтаксическую справку, а она делает все остальное.
источник
argparse
тем , что не являюсь ни программистом, ни пользовательским интерфейсом, ни дружественным к пользователю.Некоторые ценные комментарии уже предоставлены (@Florian, Basile), но позвольте мне добавить ... OP говорит,
Но также замечания:
Вы должны учитывать свою целевую аудиторию - продвинутых администраторов . На какой платформе они обычно работают - Win / Unix / Mac? А на какой платформе вы запускаете приложение? Следуйте тем соглашениям CLI, которые уже созданы для этой платформы. Ваши "продвинутые" администраторы хотят / нуждаются в инструменте на основе GUI?
Вы хотите, чтобы интерфейс был согласованным внутри и с другими инструментами администратора. Я не хочу останавливаться и думать, это
cmd -p <arg>
илиcmd -p:<arg>
илиcmd /p <arg>
. Нужны ли цитаты, потому что есть пробел? Могу ли яcmd -p <val1> <val2>
илиcmd -p <val1> -p <val2>
для нескольких целей? Они заказывают конкретно? Перегружаемые? Тожеcmd -p2 <arg> -p1 <arg>
работает? Есть лиls -l -r -t dir1 dir2
==ls -trl dir1 dir2
?Что касается инструментов администрирования Unix, я всегда помнил руководство Shelldorado от Heiner's вместе с другими упомянутыми ссылками.
Не менее важно, чем проектирование интерфейса командной строки, убедиться, что ваше приложение разработано для работы с аргументами командной строки, такими же, как в графическом интерфейсе, то есть: нет бизнес-логики в графическом интерфейсе или использовать общую команду, вызываемую как из графического интерфейса, так и из интерфейса командной строки.
Большинство основанных на UNIX инструментов администрирования фактически спроектированы вначале как инструменты командной строки, а предоставленный графический интерфейс пользователя просто облегчает «заполнение» параметров командной строки. Такой подход позволяет автоматизировать, использовать файлы ответов и т. Д., А также осуществлять управление на расстоянии (меньше работы для меня!)
В качестве классического набора инструментов используется этот подход - Tcl / Tk . Не предлагает вам переключать инструменты; просто рассмотрите подход к проектированию, начиная с написания административного приложения на основе GUI и заканчивая приложением в качестве инструмента командной строки; затем слой GUI сверху для удобства. В какой-то момент вы, вероятно, обнаружите, что графический интерфейс является болезненным (и подверженным ошибкам), если вам придется выполнять несколько конфигураций и повторно вводить одни и те же параметры снова и снова, и вы будете искать автоматический подход.
Помните, что ваш администратор, вероятно, все равно должен вводить правильные значения в правильные поля, так сколько усилий вы все равно освобождаете с помощью GUI?
источник