我想解析一组看起来像这样的命令行参数:
-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
是文件路径(甚至引用)时,\
会导致解析器将所有内容放到右侧。我通过覆盖我自己从OptionSet
继承的NDesk.Options.OptionSet
类的解析方法来解决这个问题,但是我想知道是否有任何库可以处理这种功能。盒子?
更新
对不起它不是\
我认为它是:
无论如何一组失败的例子是:
-sSetting=C:\Temp
-sSetting="C:\Temp"
-s"Setting=C:\Temp"
它们都以OptionException Error: Found 3 option values when expecting 2.
答案 0 :(得分:5)
更新:更新以处理设置值中的冒号。
好的,所以在这里你遇到了NDesk.Options的隐式默认值之一,即在多值参数中,:
和=
都被视为值分隔符,这意味着{ {1}}解析为3个值(Setting,C,\ Path)而不是预期的两个值。
为了解决这个问题,您只需修改Setting=C:\Path
选项定义,仅将-s
视为有效的分隔符,方法是编写=
而不是"s={=}"
。
原始回答,当涉及反斜杠时。
我使用了NDesk.Options,没有遇到引用路径和反斜杠的任何问题。
这是我的示例程序:
"s="
您将看到定义与我的定义之间存在差异: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设置或s设置中,我没有遇到任何有关反斜杠的问题。您是否可以尝试运行NDesk.Options版本0.2.1的程序并显示哪些值失败?
以下是我运行的一些示例,这些示例都已成功解析:
p
以下是一些产生另一个值得一提的结果的解析:
-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"
注意:如果这改变了什么,我在项目中使用Options.cs源代码文件运行NDesk.Options,而不是使用已编译的DLL。
答案 1 :(得分:3)
我成功使用了Command Line Parser Library一段时间了。效果很好,很简单,and paths with quotes are allowed。
答案 2 :(得分: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]);
}
之后,一组简单的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 here甚至可以使用编码示例)。
希望这比我之前给你的答案更有用。
答案 3 :(得分:0)
您可以在一个字符串中加入所有参数,然后可以使用正则表达式:
((?<SkeyvaluePair>-s(?<key>[^=]+)\s*=\s*(?<value>[^-]+))|(?<PkeyvaluePair>-p(?<Pvalue>[^-]+)))*
然后将字符串分成组
var groups = new Regex(yourRegex).Match(message).Groups;
并提取您需要的信息
var pairs = groups["keyvaluepair"].Captures.Cast<Capture>()
答案 4 :(得分: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);
}
}