4

次のようなコマンドライン引数のセットを解析したい:

-p[project file path] -s[name 1]=[value 1] ... -s[name n]=[value n]

正確に 1 つのプロジェクトpと任意の数の設定がある場合s

使ってみましたNDesk.Options

var set = new OptionSet {
    { "p=", "the project file", v => { /* do stuff */ } },
    { "s=", "a setting", (m, v) =>  { /* do stuff */ } },
};

これはほとんどの場合うまく機能しvalueますが、ファイル パスが (引用符で囲まれていても) の場合\、パーサーはすべてを右にドロップします。OptionSetから継承した独自のクラスで parse メソッドをオーバーライドすることで、これをハッキングしましNDesk.Options.OptionSetたが、この種の機能をすぐに処理できるライブラリがあるかどうか疑問に思っていましたか?

アップデート

申し訳ありませんが\:失敗した例のセットは次のとおりです。

-sSetting=C:\Temp
-sSetting="C:\Temp"
-s"Setting=C:\Temp"

それらはすべて失敗しますOptionException Error: Found 3 option values when expecting 2.

4

5 に答える 5

5

UPDATE : 設定値でコロンを処理するように更新します。

OK、ここでNDesk.Optionsの暗黙のデフォルトの 1 つに出くわします。これは、多値パラメータで、 と の両方:=値の区切り記号と見なされます。つまりSetting=C:\Path、期待値ではなく 3 つの値 (Setting、C、\Path) として解析されます2。

これを修正するには-s=."s={=}"の代わりに"s=".

バックスラッシュに関する元の回答。

NDesk.Optionsを使用しましたが、引用符で囲まれたパスとバックスラッシュに関する問題は発生しませんでした。

これが私のサンプルプログラムです:

public static void Main(string[] args)
{
    string parsedPath = null;
    Dictionary<string, string> parsedValues = new Dictionary<string, string>();
    var set = new OptionSet() 
    { 
        { "p=", "the project path", v => parsedPath = v }, 
        { "s=", "a setting", (m, v) => { parsedValues.Add(m, v); } },
    };
    set.Parse(args);
    Console.WriteLine(parsedPath ?? "<NULL>");
    foreach (var keyValuePair in parsedValues)
    {
        Console.WriteLine(keyValuePair.Key + "::::" + keyValuePair.Value);
    }
}

あなたの定義と私の定義には違いがあることがわかります。p=つまり、オプションに必要な値があることを意味し、あなたの定義はそれpがブール値のフラグ値であることを意味します。

p 設定でも s 設定でも、バックスラッシュに関する問題は発生していません。NDesk.Optionsのバージョン 0.2.1 でプログラムを実行してみて、どの値が失敗するかを示していただけますか?

以下は、私が実行したいくつかのサンプルで、すべて正常に解析されました。

-p=..\Path
-p..\Path
-pC:\Hello
-pHello\World
-p"Hello\World"
-s"Greeting=Hello\World"
-sGreeting="Hello\World"
-sGreeting=Hello\World
-sGreeting="Hello\My World"
-s"Greeting=Hello\My World"

言及に値する別の結果を生成するいくつかの解析を次に示します。

-sGreeting=Hello\My World -- // This gives Greeting="Hello\My" 

注: これで何かが変わる場合は、コンパイル済みの DLL ではなく、プロジェクトの Options.cs ソース コード ファイルを使用して NDesk.Options を実行しました。

于 2013-04-19T10:25:04.547 に答える
2

次のようなものを使用すると、すべての分割が行われます。

public static void Main(string[] args)
   {
       List<string> Settings = new list
       Console.WriteLine("parameter qty = {0}", args.Length);
       for(int i = 0; i < args.Length; i++)
       {
           Console.WriteLine("Arg[{0}] = [{1}]", i, args[i]);
       }

その後、各引数に基づいて必要なアクションを取得するには、単純な一連の if で十分です。引数配列内の各引数を反復処理して、必要に応じて文字列一致または正規表現を使用して、それらが準拠する引数を確認できます。たとえば、for ループにいくつかのコードを追加できます。

public static void Main(string[] args)
   {
       List<string> Settings = new List<string>();
       Console.WriteLine("parameter qty = {0}", args.Length);
       for(int i = 0; i < args.Length; i++)
       {
           Console.WriteLine("Arg[{0}] = [{1}]", i, args[i]);
           if (i>0)
               {
                   // this gives you a nice iterable list of settings
                   Setting.Add(args[i]);
               }
       }
       foreach(string setting in Settings)
           {
               //do the desired action
           }
    }

補遺: ただし、これは基本的な機能のみを提供します (私のように C++ から来て、自分で何かをしなければならない場合は問題ありませんが、C# 開発者の観点からはあまり良くないことに気づきました)、処理する必要があります。自分でバリアント コマンドを解析する (コメント/p--p or /Project= -Project=で述べたように、バリアントはすべて作成したコードで処理する必要があります)。ただし、すぐに使用できるソリューションとして、Ndesk.OptionsまたはMono.Optionsをお勧めします。 どちらも同様に機能します。移植性が重要な場合は、Mono.Options を使用する傾向があります。

使用中は、コードを次のように変更できます

var set = new OptionSet {
    { "p=|project=", "the project file", v => { /* do stuff */ } },
    { "s=|setting=", "a setting", (m, v) =>  { /* do stuff */ } },
};

そして、それがあなたが望む種類の機能を提供することを願っています(ページの最後にある ndesk hereの例には、コード化された見本もあります)。

これが私の以前の回答よりも役立つことを願っています。

于 2013-04-19T10:21:47.507 に答える
0

すべての引数を 1 つの文字列に結合して、正規表現を使用できます。

((?<SkeyvaluePair>-s(?<key>[^=]+)\s*=\s*(?<value>[^-]+))|(?<PkeyvaluePair>-p(?<Pvalue>[^-]+)))*

次に、文字列をグループに分割します

var groups = new Regex(yourRegex).Match(message).Groups;

必要な情報を抽出するよりも

var pairs = groups["keyvaluepair"].Captures.Cast<Capture>() 
于 2013-04-19T09:39:39.503 に答える
0
class Program
    {
        static void Main(string[] args)
        {
            string cmd = "car.exe -ip 1.18.4.156 -port 123";
            string hostname = "localhost";
            string port = "5505";

            string[] array = cmd.Split(' ');

            int hostnameIndex = Array.FindIndex(array, key => key == "-ip");
            int portIndex = Array.FindLastIndex(array, key => key == "-port");

            if (hostnameIndex != -1)
            {
                hostname = array[hostnameIndex + 1];
            }

            if (portIndex != -1)
            {
                port = array[portIndex + 1];
            }

            Console.WriteLine("ip :" + hostname);
            Console.WriteLine("port :" + port);

        }
    }
于 2014-09-20T17:44:40.233 に答える