Каков шаблон проектирования для обработки аргументов командной строки - PullRequest
44 голосов
/ 10 сентября 2008

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

Рассмотрим:

myprogram -f filename -d directory -r regex

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

Ответы [ 16 ]

15 голосов
/ 23 сентября 2011

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

Вы должны посмотреть на применение шаблона шаблона (метод шаблона в «Шаблонах проектирования» [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

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

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

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

14 голосов
/ 10 сентября 2008

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

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

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

5 голосов
/ 10 сентября 2008

Вы не упомянули язык, но для Java нам очень понравился Apache Commons CLI . Для C / C ++, getopt.

4 голосов
/ 10 мая 2014

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

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

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

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

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

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

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

4 голосов
/ 17 сентября 2008

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

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

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

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

2 голосов
/ 21 сентября 2008

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

2 голосов
/ 10 сентября 2008

Я предпочитаю такие опции, как "-t текст" и "-i 44"; Мне не нравятся "-fname" или "--very-long-arguments = 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's 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's not a switch that begins with '-' or '/', so it's the primary option
            Primary = Arg;

            break;
         }
      }

   // Done
   return (0);
   }
2 голосов
/ 10 сентября 2008

Предполагая, что у вас есть объект "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;
    }
}
2 голосов
/ 10 сентября 2008

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

1 голос
/ 28 июля 2016

Как насчет шаблона интерпретатора? http://www.dofactory.com/net/interpreter-design-pattern

...