Hva er design mønster for behandling kommandolinjeargumentene

stemmer
41

Hvis du skriver et program som er kjørbar fra kommandolinjen, du ofte ønsker å tilby brukeren flere alternativer eller flagg, sammen med muligens mer enn ett argument. Jeg har snublet meg gjennom dette mange ganger, men er det noen slags design mønster for looping gjennom args og ringer de aktuelle handler funksjoner?

Ta i betraktning:

myprogram -f filename -d directory -r regex

Hvordan organiserer du behandleren funksjoner når du henter argumentene hjelp uansett bygde-ins for ditt språk? (Språkspesifikke svar imot, hvis det hjelper deg å artikulere et svar)

Publisert på 10/09/2008 klokken 15:33
kilden bruker
På andre språk...                            


16 svar

stemmer
13

Jeg vet ikke av noen dokumenterte "mønstre" for behandling.

Jeg tror en av de eldste biblioteker / APIer for håndtering argumenter er getopt. Googling "getopt" viser mange man-sidene og lenker til implementeringer.

Vanligvis har jeg et preferanser eller innstillinger i søknaden min at argumentet prosessoren vet hvordan man skal kommunisere med. Argumenter blir deretter oversatt til noe i denne tjenesten at søknaden enn da spørre. Dette kan være så enkelt som en ordbok med innstillinger (som en streng innstilling heter "filnavn").

Svarte 10/09/2008 kl. 15:41
kilden bruker

stemmer
1

Jeg vil anbefale å bruke en kommandolinjebehandleren bibliotek. Noen russisk fyr opprettet en anstendig en, men det er tonnevis av dem der ute. Vil spare deg litt tid slik at du kan konsentrere deg om formålet med programmet i stedet for parsing kommandolinjebryterne!

Svarte 10/09/2008 kl. 15:42
kilden bruker

stemmer
5

Du nevnte ikke språket, men for Java vi har elsket Apache Commons CLI . For C / C ++, getopt.

Svarte 10/09/2008 kl. 15:44
kilden bruker

stemmer
0

Du nevner ikke et språk for dette, men hvis du er ute etter en veldig fin Objective-C wrapper rundt getopt da Dave Dribin sin DDCLI rammeverket er veldig hyggelig.

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

Svarte 10/09/2008 kl. 15:47
kilden bruker

stemmer
0

Jeg bruker getopts :: std og getopts :: lang i Perl og også den getopt funksjon i C. Dette standardiserer analyser og formatet av parametere. Andre språk har ulike mekanismer for å håndtere disse.

Håper dette hjelper

Svarte 10/09/2008 kl. 15:47
kilden bruker

stemmer
0

Den standard design følger som regel hva getopt gjør, det er getopt biblioteker for mange språk, .NET, python, C, Perl, PHP, osv

Den grunnleggende utformingen er å ha en kommandolinje parser som returnerer del for del argumentene som er sendt for å bli kontrollert i en sløyfe.

Denne artikkelen drøfter den i litt mer detalj.

Svarte 10/09/2008 kl. 15:47
kilden bruker

stemmer
1

Getopt er den eneste veien å gå.

http://sourceforge.net/projects/csharpoptparse

Svarte 10/09/2008 kl. 15:51
kilden bruker

stemmer
2

Den boost :: program_options biblioteket er fint om du er i C ++ og har luksusen av å bruke Boost.

Svarte 10/09/2008 kl. 16:09
kilden bruker

stemmer
0

Jeg er ikke så interessert i bibliotekene, selv om det er definitivt nyttig. Jeg var ute mer for noen "pseudo-kode" som illustrerer behandling av si gjennomsnittlig haug med flagg og en haug med lengre argumenter, som et eksempel.

Svarte 10/09/2008 kl. 16:13
kilden bruker

stemmer
2

Forutsatt at du har en "config" objekt som du tar sikte på å sette opp med flagg og en passende kommandolinje parser som tar seg av parsing kommandolinjen og leverer en konstant strøm av alternativene, her går en blokk med pseudo

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;
    }
}
Svarte 10/09/2008 kl. 16:57
kilden bruker

stemmer
2

Jeg foretrekker alternativer som "-t tekst" og "-i 44"; Jeg liker ikke "-fname" eller "--very lang-argumentet = some_value".

Og "-", "-h", og "/ h" alle produserer en hjelpefunksjon.

Her er hvordan koden min ser ut:

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);
   }
Svarte 10/09/2008 kl. 18:04
kilden bruker

stemmer
4

Noen kommentarer på dette ...

Først, mens det ikke er noen mønstre i seg selv, skriver en parser er egentlig en mekanisk øvelse, siden gitt en grammatikk, kan en parser enkelt genereres. Verktøy som Bison, og ANTLR kommer til hjernen.

Når det er sagt, parser generatorer er vanligvis overkill for kommandolinjen. Så det vanlige mønsteret er å skrive en selv (som andre har vist) et par ganger før du blir syk av å håndtere den kjedelige detaljer og finne et bibliotek for å gjøre det for deg.

Jeg skrev en for C ++ som sparer en haug med innsats som getopt formidler og gjør fin bruk av maler: TCLAP

Svarte 16/09/2008 kl. 22:39
kilden bruker

stemmer
2

Jeg riffing på ANTLR svaret ved mes5k. Denne koblingen til Codeproject er for en artikkel som omhandler ANLTR og bruke besøket mønster for å gjennomføre de handlingene du ønsker deg appen ta. Det er godt skrevet og verdt å vurdere.

Svarte 21/09/2008 kl. 16:28
kilden bruker

stemmer
13

Jeg tror følgende svar er mer langs linjene av hva du leter etter:

Du bør se på å bruke malen Pattern (Mal Method in "Design Patterns" [Gamma, el al])

Kort sagt er det generelle behandlingen ser slik ut:

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

Kort sagt, gjennomføre en ConsoleEngineBase klasse som har metoder for:

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

Deretter oppretter du et chassis, som instantiates en ConsoleEngine () forekomst og sender hoved () melding å sparke den av.

For å se et godt eksempel på hvordan man skal bruke dette til en konsoll eller kommandolinje program sjekk ut følgende link: http://msdn.microsoft.com/en-us/magazine/cc164014.aspx

Eksempelet er i C #, men ideene er lett implementeres i andre miljøer.

Du vil se på getopt () som bare den delen som passer oss inn i argumentet håndtering (pre-behandling).

Håper dette hjelper.

Svarte 23/09/2011 kl. 13:45
kilden bruker

stemmer
4

Vel, ville dens et gammelt innlegg, men jeg fremdeles liker å bidra. Spørsmålet var ment på valg av design patterns men jeg kunne se en masse diskusjon om hvilket bibliotek som skal brukes. Jeg har sjekket ut microsoft link as per Lindsay som snakker om mal design mønster å bruke.

Men jeg er ikke overbevist med innlegget. Mal mønster hensikt er å definere en mal som vil bli gjennomført av forskjellige andre klasser for å ha lik oppførsel. Jeg tror ikke parsing kommandolinjen passer inn i den.

Jeg vil heller gå med "Command" design mønster. Dette mønsteret er best egnet til menystyrte alternativer.

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

slik at i tilfelle f, -d og -R hele blir kommandoene som har felles eller separat mottaker definert. På den måten flere mottakere kan defineres i fremtiden. Det neste trinn vil være å kjede dette ansvaret for kommandoer, i tilfelle der en behandlingskjede nødvendig. For som jeg ville velge.

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

Jeg antar en kombinasjon av disse to er best å organisere koden for kommandolinje behandling eller noen menystyrt tilnærming.

Svarte 10/05/2014 kl. 16:04
kilden bruker

stemmer
1

Hva med tolken mønster? http://www.dofactory.com/net/interpreter-design-pattern

Svarte 28/07/2016 kl. 16:12
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more