如何让NDesk在命令行解析多参数列表
本文关键字:参数 列表 命令行 NDesk | 更新日期: 2023-09-27 17:57:58
如何让NDesk在命令行(C#)解析多参数列表?
我有两个标志,它们都接受多个参数(文件列表)。一个是-j,另一个是-c。但我认为NDesk要求每个参数前面都加上-j/-c)
例如,我想要:
%> main -j file1.j file2.j file3.j -c file4.c file5.c file6.c file7.c
让它生成两个列表,一个包含.j文件,另一个包含.c文件。但是,它希望以这种方式列出的每个文件前面都有标志。
因此,这将起作用:
%> main -j file1.j -j file2.j -j file3.j -c file4.c -c file5.c -c file6.c -c file7.c
尽管我宁愿有第一个版本。
有没有办法用NDesk.Options库做到这一点?我已经阅读了大部分文档,但我不认为是。
有一种方法可以做到这一点,但只需要很少的破解。NDesk使用"<>"作为特殊的默认处理程序。您所做的是跟踪"当前"参数,然后让默认处理程序根据当前参数决定如何处理这些值。下面是一个示例,我将这些值放入字典中。
static void Main(string[] args)
{
string currentParameter = "";
Dictionary<string, List<string>> parameters = new Dictionary<string, List<string>>();
OptionSet set = new OptionSet() {
{ "c", ".c files", v => currentParameter = "c" },
{ "j", ".j files", v => currentParameter = "j" },
{ "<>", v => {
List<string> values;
if (parameters.TryGetValue(currentParameter, out values))
{
values.Add(v);
}
else
{
values = new List<string> { v };
parameters.Add(currentParameter, values);
}
}
}
};
set.Parse(args);
foreach (var parameter in parameters)
{
Console.WriteLine("Parameter: {0}", parameter.Key);
foreach (var value in parameter.Value)
{
Console.WriteLine("'t{0}", value);
}
}
}
输出为:
参数:j
文件1.j
文件2.j
文件3.j
参数:c
文件4.c
文件5.c
文件6.c
file7.c
另一种方法是覆盖此处列出的OptionSet.Parse
该示例描述了一种更彻底的"串联/附加"方法,该方法将解析所有格式,但如果您只对处理-flag value1 value2 value3 ... valueN
感兴趣,则可以使用:
public class MultiOptionSet : OptionSet
{
private string lastArg;
private Option lastOption;
protected override bool Parse(string argument, OptionContext c)
{
// based on example in http://www.ndesk.org/doc/ndesk-options/NDesk.Options/Option.html#M:NDesk.Options.Option.OnParseComplete(NDesk.Options.OptionContext)
string f, n, s, v;
bool haveParts = GetOptionParts(argument, out f, out n, out s, out v);
// reset placeholder for next multiple if we are looking at a flagged argument name
if( haveParts )
{
lastArg = f + n;
}
// are we after a flagged argument name, without parts (meaning a value)
else
{
// remember for next time, in case it's another value
if( null != c.Option ) lastOption = c.Option;
// but if the 'last arg' wasn't already provided, we reuse the one we set last time
else
{
c.Option = lastOption;
c.OptionName = lastArg;
}
c.OptionValues.Add(argument); // add the value to be invoked
c.Option.Invoke(c); // perform the 'setter'
return true;
}
return base.Parse(argument, c);
}
}