문제

명령줄에서 실행 가능한 프로그램을 작성하는 경우 사용자에게 둘 이상의 인수와 함께 여러 옵션이나 플래그를 제공하려는 경우가 많습니다.나는 이 문제를 여러 번 헤쳐나갔지만 인수를 통해 반복하고 적절한 처리기 함수를 호출하기 위한 일종의 디자인 패턴이 있습니까?

고려하다:

myprogram -f filename -d directory -r regex

언어에 내장된 기능을 사용하여 인수를 검색한 후 처리기 함수를 어떻게 구성합니까?(답변을 명확히 하는 데 도움이 된다면 언어별 답변을 환영합니다)

도움이 되었습니까?

해결책

나는 처리를 위해 문서화된 "패턴"을 모릅니다.

나는 인수 처리를 위한 가장 오래된 라이브러리/API 중 하나가 getopt라고 생각합니다.인터넷 검색 "getopt"를 검색하면 많은 매뉴얼 페이지와 구현 링크가 표시됩니다.

일반적으로 내 애플리케이션에는 인수 프로세서가 통신하는 방법을 알고 있는 기본 설정 또는 설정 서비스가 있습니다.그런 다음 인수는 이 서비스에서 애플리케이션이 쿼리하는 항목으로 변환됩니다.이는 설정 사전(예: "filename"이라는 문자열 설정)만큼 간단할 수 있습니다.

다른 팁

나는 다음 대답이 당신이 찾고 있는 것과 더 일치한다고 생각합니다.

템플릿 패턴("Design Patterns" [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()를 살펴보겠습니다.

도움이 되었기를 바랍니다.

언어에 대해서는 언급하지 않았지만 우리가 좋아하는 Java에 대해서는 언급하지 않았습니다. 아파치 커먼즈 CLI.C/C++의 경우 getopt.

이에 대한 몇 가지 의견 ...

첫째, 그 자체로는 패턴이 없지만 파서를 작성하는 것은 본질적으로 기계적인 작업입니다. 문법이 주어지면 파서는 쉽게 생성될 수 있기 때문입니다.Bison 및 ANTLR과 같은 도구가 떠오릅니다.

즉, 파서 생성기는 일반적으로 명령줄에 비해 과잉입니다.따라서 일반적인 패턴은 지루한 세부 사항을 처리하는 데 지쳐서 이를 수행할 라이브러리를 찾을 때까지 직접 작성하는 것입니다(다른 사람들이 보여주듯이).

나는 getopt가 템플릿을 전달하고 잘 활용하는 많은 노력을 절약해주는 C++용 하나를 작성했습니다. TCLAP

글쎄, 오래된 게시물이지만 여전히 기여하고 싶습니다.질문은 디자인 패턴 선택에 관한 것이었지만 어떤 라이브러리를 사용할지에 대한 많은 논의를 볼 수 있었습니다.사용할 템플릿 디자인 패턴에 대해 이야기하는 lindsay에 따라 Microsoft 링크를 확인했습니다.

그러나 나는 그 게시물에 확신이 없습니다.템플릿 패턴의 목적은 다양한 다른 클래스에 의해 구현되어 균일한 동작을 갖도록 템플릿을 정의하는 것입니다.나는 구문 분석 명령 줄이 적합하지 않다고 생각합니다.

차라리 "Command" 디자인 패턴을 사용하고 싶습니다.이 패턴은 메뉴 기반 옵션에 가장 적합합니다.

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

따라서 귀하의 경우 -f, -d 및 -r은 모두 공통 또는 별도의 수신자가 정의된 명령이 됩니다.이렇게 하면 앞으로 더 많은 수신자를 정의할 수 있습니다.다음 단계는 처리 체인이 필요한 경우에 대비해 이러한 명령 책임을 연결하는 것입니다.나는 그것을 선택할 것입니다.

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

명령줄 처리나 메뉴 ​​기반 접근 방식을 위한 코드를 구성하는 데는 이 두 가지의 조합이 가장 적합하다고 생각합니다.

그만큼 부스트::프로그램_옵션 C++을 사용하고 있고 Boost를 사용할 여유가 있다면 라이브러리가 좋습니다.

플래그를 사용하여 설정하려는 "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;
    }
}

나는 "-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'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);
   }

나는 mes5k의 ANTLR 답변을 읽고 있습니다.이것 코드프로젝트 링크 ANLTR에 대해 설명하고 방문 패턴을 사용하여 앱에서 수행할 작업을 구현하는 문서입니다.잘 쓰여졌고 검토할 가치가 있습니다.

명령줄 프로세서 라이브러리를 사용하는 것이 좋습니다. 어떤 러시아 남자 괜찮은 것을 만들었지만 거기에는 수많은 것들이 있습니다.명령줄 스위치를 구문 분석하는 대신 앱의 목적에 집중할 수 있도록 시간을 절약할 수 있습니다!

Getopt가 유일한 방법입니다.

http://sourceforge.net/projects/csharpoptparse

인터프리터 패턴은 어떻습니까?http://www.dofactory.com/net/interpreter-design-pattern

이에 대한 언어는 언급하지 않았지만 getopt에 대한 정말 멋진 Objective-C 래퍼를 찾고 있다면 Dave Dribin의 DDCLI 프레임워크가 정말 좋습니다.

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

나는 Getopts::std 그리고 Getopts::긴 Perl에서도 Getopt C에서 함수를 사용합니다.이는 매개변수의 구문 분석 및 형식을 표준화합니다.다른 언어에는 이를 처리하기 위한 다른 메커니즘이 있습니다.

도움이 되었기를 바랍니다

표준 디자인은 일반적으로 getopt의 기능을 따르며, .NET, Python, C, Perl, PHP 등 다양한 언어에 대한 getopt 라이브러리가 있습니다.

기본 설계는 루프에서 확인하기 위해 전달된 인수를 부분적으로 반환하는 명령줄 파서를 갖는 것입니다.

이것 기사에서는 이에 대해 좀 더 자세히 설명합니다.

나는 도서관에 그다지 관심이 없지만 그것이 확실히 도움이 됩니다.예를 들어 평균 플래그 묶음과 더 긴 인수 묶음의 처리를 보여주는 "의사 코드"를 더 찾고 있었습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top