Каков шаблон проектирования для обработки аргументов командной строки

Если вы пишете исполняемую программу из командной строки, вы часто хотите предложить пользователю несколько опций или флагов, а также, возможно, более одного аргумента. Я наткнулся на это много раз, но есть ли какой-то шаблон дизайна для прокрутки аргументов и отработки соответствующих функций?

Рассмотрим:

myprogram -f filename -d directory -r regex

Как вы упорядочиваете код после извлечения аргументов с использованием любых встроенных модулей для вашего языка? (приветствуются ответы на конкретные языки, если это поможет вам сформулировать ответ)

Ответ 1

Я не знаю никаких документированных "шаблонов" для обработки.

Я считаю, что одной из самых старых библиотек /API для обработки аргументов является getopt. Googling "getopt" показывает много справочных страниц и ссылок на реализации.

Как правило, у меня есть служба предпочтений или настроек в моем приложении, что процессор аргументов знает, как с ним общаться. Аргументы затем переводятся на что-то в этой службе, чем приложение, чем запрос. Это может быть так же просто, как словарь настроек (например, строковый параметр с именем "имя файла" ).

Ответ 2

Я думаю, что следующий ответ более соответствует тем, что вы ищете:

Вы должны взглянуть на применение шаблона шаблона (метод шаблона в "шаблонах проектирования" [Gamma, el al])

Короче, общая обработка выглядит следующим образом:

If the arguments to the program are valid then
    Do necessary pre-processing
    For every line in the input
        Do necessary input processing
    Do necessary post-processing
Otherwise
    Show the user a friendly usage message

Короче говоря, реализуем класс ConsoleEngineBase, который имеет методы для:

PreProcess()
ProcessLine()
PostProcess()
Usage()
Main()

Затем создайте шасси, которое создает экземпляр экземпляра ConsoleEngine() и отправляет сообщение Main(), чтобы отключить его.

Чтобы увидеть хороший пример того, как применить это к консоли или командной строке, проверьте следующую ссылку: http://msdn.microsoft.com/en-us/magazine/cc164014.aspx

Пример приведен в С#, но идеи легко реализуются в любой другой среде.

Вы бы посмотрели на GetOpt() как на часть, которая вписывается в обработку аргументов (предварительная обработка).

Надеюсь, что это поможет.

Ответ 3

Вы не упомянули язык, но для Java мы любили Apache Commons CLI. Для C/С++, getopt.

Ответ 4

Несколько комментариев об этом...

Во-первых, хотя шаблонов не существует, писать парсер по существу является механическим упражнением, поскольку с учетом грамматики парсер можно легко сгенерировать. Инструменты, такие как Bison и ANTLR, приходят на ум.

Тем не менее, генераторы синтаксического анализатора, как правило, переполняются для командной строки. Таким образом, обычная картина заключается в том, чтобы написать один (как показали другие) несколько раз, пока вам не надоедает работа с утомительными деталями и найдите библиотеку, чтобы сделать это за вас.

Я написал один для С++, который сэкономит кучу усилий, которые приносит getopt и делает приятное использование шаблонов: TCLAP

Ответ 5

Ну, это старый пост, но я все равно хотел бы внести свой вклад. Вопрос был направлен на выбор шаблонов проектирования, однако я мог видеть много дискуссий о том, какую библиотеку использовать. Я проверил связь Microsoft в соответствии с lindsay, в которой говорится о шаблоне шаблона для использования.

Однако я не уверен в этом сообщении. Цель шаблона шаблона состоит в том, чтобы определить шаблон, который будет реализован различными другими классами, чтобы иметь однородное поведение. Я не думаю, что синтаксический анализ командной строки вписывается в нее.

Я предпочел бы использовать шаблон дизайна "Command". Этот шаблон лучше всего подходит для опций, управляемых меню.

http://www.blackwasp.co.uk/Command.aspx

поэтому в вашем случае -f, -d и -r все становятся командами, которые имеют общий или отдельный приемник. Таким образом, в будущем можно определить большее количество приемников. Следующим шагом будет объединение этих обязанностей команд, если требуется цепочка обработки. Для чего я бы выбрал.

http://www.blackwasp.co.uk/ChainOfResponsibility.aspx

Я думаю, что сочетание этих двух лучше всего организовать код для обработки командной строки или любой подход, управляемый меню.

Ответ 6

Библиотека boost:: program_options хороша, если вы на С++ и можете использовать Boost.

Ответ 7

Предполагая, что у вас есть объект "config", который вы хотите установить с помощью флагов и подходящий синтаксический анализатор командной строки, который заботится о синтаксическом анализе командной строки и предоставляет постоянный поток параметров, здесь идет блок псевдокода

while (current_argument = cli_parser_next()) {
    switch(current_argument) {
        case "f": //Parser strips the dashes
        case "force":
            config->force = true;
            break;
        case "d":
        case "delete":
            config->delete = true;
            break;
        //So on and so forth
        default:
            printUsage();
            exit;
    }
}

Ответ 8

Я предпочитаю такие опции, как "-t text" и "-i 44"; Мне не нравится "-fname" или "--very-long-argument = some_value".

И "-?", "-h" и "/h" создают экран справки.

Вот как выглядит мой код:

int main (int argc, char *argv[])
   {  int i;
      char *Arg;
      int ParamX, ParamY;
      char *Text, *Primary;

   // Initialize...
   ParamX = 1;
   ParamY = 0;
   Text = NULL;
   Primary = NULL;

   // For each argument...
   for (i = 0; i < argc; i++)
      {
      // Get the next argument and see what it is
      Arg = argv[i];
      switch (Arg[0])
         {
         case '-':
         case '/':
            // It an argument; which one?
            switch (Arg[1])
               {
               case '?':
               case 'h':
               case 'H':
                  // A cry for help
                  printf ("Usage:  whatever...\n\n");
                  return (0);
                  break;

               case 't':
               case 'T':
                  // Param T requires a value; is it there?
                  i++;
                  if (i >= argc)
                     {
                     printf ("Error:  missing value after '%s'.\n\n", Arg);
                     return (1);
                     }

                  // Just remember this
                  Text = Arg;

                  break;

               case 'x':
               case 'X':
                  // Param X requires a value; is it there?
                  i++;
                  if (i >= argc)
                     {
                     printf ("Error:  missing value after '%s'.\n\n", Arg);
                     return (1);
                     }

                  // The value is there; get it and convert it to an int (1..10)
                  Arg = argv[i];
                  ParamX = atoi (Arg);
                  if ((ParamX == 0) || (ParamX > 10))
                     {
                     printf ("Error:  invalid value for '%s'; must be between 1 and 10.\n\n", Arg);
                     return (1);
                     }

                  break;

               case 'y':
               case 'Y':
                  // Param Y doesn't expect a value after it
                  ParamY = 1;
                  break;

               default:
                  // Unexpected argument
                  printf ("Error:  unexpected parameter '%s'; type 'command -?' for help.\n\n", Arg);
                  return (1);
                  break;
               }

            break;

         default:
            // It not a switch that begins with '-' or '/', so it the primary option
            Primary = Arg;

            break;
         }
      }

   // Done
   return (0);
   }

Ответ 9

Я разбираюсь в ответе ANTLR на mes5k. Эта ссылка для Codeproject предназначена для статьи, в которой обсуждается ANLTR и используется шаблон посещения для реализации действий, которые вы хотите, чтобы приложение было выполнено. Он хорошо написан и заслуживает внимания.

Ответ 10

Я бы рекомендовал использовать библиотеку процессоров командной строки. Какой-то российский парень создал приличный, но их там много. Вы сэкономите некоторое время, чтобы сосредоточиться на цели своего приложения, а не на синтаксическом анализе командной строки!

Ответ 13

Вы не укажете язык для этого, но если вы ищете действительно приятную обертку Objective-C вокруг getopt, тогда структура Dave DribL Dave действительно хороша.

http://www.dribin.org/dave/blog/archives/2008/04/29/ddcli

Ответ 14

Я использую Getopts:: std и Getopts:: long в perl, а также Getopt в C. Это стандартизирует синтаксический анализ и формат параметров. Другие языки имеют разные механизмы для их обработки.

Надеюсь, что это поможет

Ответ 15

Стандартная конструкция обычно следует за тем, что делает getopt, есть библиотеки getopt для многих языков,.NET, python, C, Perl, PHP и т.д.

Основной проект - иметь синтаксический анализатор командной строки, который по частям возвращает часть аргументов, которые должны быть проверены в цикле.

В этой статье мы обсудим ее более подробно.

Ответ 16

Я не так сильно интересуюсь библиотеками, хотя это определенно полезно. В качестве примера я больше искал какой-то "псевдокод", который иллюстрирует обработку, скажем, вашей средней группы флагов и кучу более длинных аргументов.