[英]How to parse command line arguments
我想解析一組看起來像這樣的命令行參數:
-p[project file path] -s[name 1]=[value 1] ... -s[name n]=[value n]
其中恰好有一個項目p
和任意數量的設置s
。
我嘗試過使用NDesk.Options
var set = new OptionSet {
{ "p=", "the project file", v => { /* do stuff */ } },
{ "s=", "a setting", (m, v) => { /* do stuff */ } },
};
這在大多數情況下效果很好,但是當value
是文件路徑(甚至引用)時, \\
會導致解析器將所有內容放到右邊。 我已經通過覆蓋我自己繼承自NDesk.Options.OptionSet
自己的OptionSet
類的parse方法來解決這個NDesk.Options.OptionSet
,但我想知道是否有任何庫可以NDesk.Options.OptionSet
處理這種功能?
UPDATE
對不起它不是\\
我認為它是:
無論如何一組失敗的例子是:
-sSetting=C:\Temp
-sSetting="C:\Temp"
-s"Setting=C:\Temp"
它們都會因OptionException Error: Found 3 option values when expecting 2.
失敗OptionException Error: Found 3 option values when expecting 2.
更新 :更新以處理設置值中的冒號。
好的,所以在這里遇到NDesk.Options的隱式默認值之一,即在多值參數中, :
和=
都被視為值分隔符,這意味着Setting=C:\\Path
解析為3個值(Setting,C ,\\ Path)而不是你預期的兩個。
為了解決這個問題,你只需修改-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"
注意:如果這改變了什么,我在項目中使用Options.cs源代碼文件運行NDesk.Options,而不是使用編譯的DLL。
我成功使用了Command Line Parser Library一段時間了。 工作得很好,很簡單, 並且允許帶引號的路徑 。
如果您使用以下內容,所有拆分都將為您完成:
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]);
}
在那之后,一組簡單的ifs應該足以根據每個參數獲得所需的操作。 您可以迭代參數數組中的每個參數,以根據您的喜好使用字符串匹配或正則表達式來查看它們符合的arg。 對於eaxmple,您可以在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 這里頁面甚至有一個編碼范例使用的結束)。
希望這比我以前給你的答案更有用。
您可以在一個字符串中加入所有參數,然后可以使用正則表達式:
((?<SkeyvaluePair>-s(?<key>[^=]+)\s*=\s*(?<value>[^-]+))|(?<PkeyvaluePair>-p(?<Pvalue>[^-]+)))*
然后將字符串拆分成組
var groups = new Regex(yourRegex).Match(message).Groups;
而不是提取你需要的信息
var pairs = groups["keyvaluepair"].Captures.Cast<Capture>()
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);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.