2008-09-10 10 views
38

コマンドラインから実行可能なプログラムを作成する場合は、複数の引数とともに複数のオプションまたはフラグをユーザに提供することがしばしばあります。私はこれまで何度も自分の道を見つけましたが、argsをループして適切な機能を停止するためのデザインパターンがありますか?コマンドライン引数を処理するためのデザインパターンは何ですか?

考えてみましょう:

myprogram -f filename -d directory -r regex 

をお使いの言語のためにどんなビルトインを使用して、引数を取得した後、どのようにコードを整理するのですか? (言語固有の回答が歓迎され、回答を明確にするのに役立つ場合)

+0

質問には、デザインパターンと提案が必要なので、これは「言語にとらわれない」とタグ付けする必要があります。 – martinatime

答えて

13

私は、処理のための文書化された "パターン"について知らない。

引数を処理するための最も古いライブラリ/ APIの1つはgetoptです。グーグル "getopt"は多くのマニュアルページと実装へのリンクを示しています。

一般に、私のアプリケーションには、引数プロセッサが通信する方法を知っているという設定や設定サービスがあります。引き数は、このサービス内の何かに変換され、そのアプリケーションは照会されます。これは、設定の辞書( "filename"という名前の文字列設定のような)と同じくらい単純なものです。

1

コマンドラインプロセッサライブラリの使用をお勧めします。 Some Russian guyはまともなものを作りましたが、そこにたくさんのものがあります。コマンドラインスイッチを解析するのではなく、アプリの目的に集中できるよう、時間を節約できます。

+0

私はこの記事が好きです。ありがとう! :-) – craigmoliver

5

言語は言及していませんが、Javaの場合はApache Commons CLIが好きでした。 C/C++の場合、getopt。

0

あなたはこれについて言及していませんが、getoptに関する本当に素晴らしいObjective-Cラッパーをお探しの場合、Dave DribinのDDCLIフレームワークは本当に素晴らしいです。私はPerlでGetopts::stdGetopts::longを使用すると、このパラメータの解析およびフォーマットを標準化しC.におけるGetopt機能

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

0

。他の言語はこれらを扱うための異なる仕組みを持っています。

希望はこれが基本的な設計はしている多くの言語、.NET、パイソン、C、PerlやPHPなど

ためのgetoptのライブラリがあり、標準的な設計は、通常のgetoptが何をするか、次の

0

を支援しますループでチェックするために渡された引数を部分的に返すコマンドラインパーサを持っています。

Thisの記事で詳しく説明しています。

2

あなたがC++にいるとブーストを使用しての贅沢を持っている場合boost::program_optionsライブラリがいいです。

+0

それは良い選択です。このライブラリは、古いgetoptと比べて少し複雑ですが、コマンドライン引数を代入または統合する設定ファイルも使用できます。 –

0

私はライブラリに興味はありませんが、間違いなく役立ちます。私は、一例として、あなたの平均的な旗の束と長い引数の束を言う、「擬似コード」をもっと探していました。

+0

ここで説明するのではなく、質問でこれを更新したい場合があります。それは答えのためのものです。 – rpattabi

2

フラグを設定することを目的とした「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

「-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); 
    } 
4

この上のいくつかのコメント...

まず、それ自体が任意のパターンが存在しない一方で、パーサを書くことは、基本的に機械的な運動です文法が与えられているので、パーサーを容易に生成することができる。 BisonやANTLRのようなツールが気になります。

つまり、パーサージェネレータは通常、コマンドラインでは過剰です。ですから、通常のパターンは、あなたが退屈な細部を扱うのがうまくいき、あなたのためにそれを行うための図書館を見つけるまで、あなた自身(ある人が実証したように)を数回書くことです。

私は与えるの努力のgetoptの束を保存し、テンプレートの素敵利用したC++のための1つを書いた:TCLAP

+0

'' TCLAP''は素晴らしいCLI解析ライブラリです。ルールの事前解析と '' argv''の構文解析のポストパース抽出は、非常に便利で直感的で、プログラムを正しいディスクリートコンポーネント(IMHO)に分割するのに役立ちます。 – Sean

2

私はmes5kでANTLRの答えにリフです。このlink to Codeprojectは、ANLTRについて説明し、訪問パターンを使用して、アプリケーションで実行するアクションを実装する記事用です。それはよく書かれ、見直す価値があります。

12

私は、次の答えはあなたが探しているものの線に沿ってより多くのだと思う:

あなたはテンプレートパターン(「デザインパターン」でのテンプレートメソッド[ガンマ、エル・アル])を適用するをご覧ください

要するに

それは全体の処理は次のようになります。

:要するに

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クラスを実装

次に、ConsoleEngine()インスタンスをインスタンス化し、Main()メッセージを送信してシャットダウンするシャーシを作成します。

は次のリンクをチェックアウトコンソールまたはコマンドラインプログラムにこれを適用する方法の良い例を参照するには、次の http://msdn.microsoft.com/en-us/magazine/cc164014.aspx

の例では、C#であるが、しかし、アイデアは簡単に他の環境で実装されています。

あなたは、GetOpt()を引数の処理(前処理)に適合する部分として見ます。

これが役に立ちます。

+1

は実装よりもむしろ概念に固執している。私はこれが選択された答えだったはずだと思う。 – Plasmarob

3

まあ、その古い投稿ですが、私はまだ貢献したいと思います。質問はデザインパターンの選択を意図していましたが、私はどのライブラリを使うべきかについて多くの議論を見ることができました。私は使用するテンプレートデザインパターンについて語るlindsayごとにマイクロソフトのリンクをチェックアウトしました。

しかし、私は投稿に納得していません。テンプレートパターンの目的は、他のさまざまなクラスによって実装されるテンプレートを定義して、一様な動作をさせることです。私はコマンドラインを解析することはそれに収まるとは思わない。

私はむしろ "コマンド"デザインパターンに行きます。このパターンは、メニュー駆動オプションに最適です。

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

ので、あなたの場合には、-f、-dと-rすべては、共通または個別の受信機が定義されたコマンドになります。そうすれば、将来、より多くの受信者を定義することができます。次のステップは、処理チェーンが必要な場合、コマンドのこれらの責任を連鎖させることです。私はそれを選ぶだろう。

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

私は、これらの二つの組み合わせを推測するコマンドライン処理または任意のメニュー駆動型のアプローチのためのコードを整理するのが最善です。

関連する問題