What is the design pattern for processing command

2020-02-07 19:45发布

If you are writing a program that is executable from the command line, you often want to offer the user several options or flags, along with possibly more than one argument. I have stumbled my way through this many times, but is there some sort of design pattern for looping through args and calling the appropriate handler functions?

Consider:

myprogram -f filename -d directory -r regex

How do you organize the handler functions after you retrieve the arguments using whatever built-ins for your language? (language-specific answers welcomed, if that helps you articulate an answer)

16条回答
对你真心纯属浪费
2楼-- · 2020-02-07 20:04

I prefer options like "-t text" and "-i 44"; I don't like "-fname" or "--very-long-argument=some_value".

And "-?", "-h", and "/h" all produce a help screen.

Here's how my code looks:

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);
   }
查看更多
趁早两清
3楼-- · 2020-02-07 20:05
乱世女痞
4楼-- · 2020-02-07 20:07

Assuming you have a "config" object that you aim to setup with the flags and a suitable command line parser that takes care of parsing the command line and supply a constant stream of the options, here goes a block of pseudocode

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;
    }
}
查看更多
做自己的国王
5楼-- · 2020-02-07 20:08

I would recommend using a command line processor library. Some Russian guy created a decent one, but there are tons of them out there. Will save you some time so you can concentrate on the purpose of your app rather than parsing command line switches!

查看更多
等我变得足够好
6楼-- · 2020-02-07 20:09

I use the Getopts::std and Getopts::long in perl and also the Getopt function in C. This standardises the parsing and format of parameters. Other languages have different mechanisms for handling these.

Hope this helps

查看更多
成全新的幸福
7楼-- · 2020-02-07 20:12
登录 后发表回答