具有互斥必需参数的命令行解析器
Posted
技术标签:
【中文标题】具有互斥必需参数的命令行解析器【英文标题】:Command Line Parser with mutually exclusive required parameters 【发布时间】:2012-05-25 05:49:00 【问题描述】:我开始将CommandLine Parser Library 用于一个同时具有 GUI 和命令行执行功能的工具。通过命令行选项启动 GUI。
因此,如果程序在命令行模式下执行,我希望有必要的选项。基本上,如果未设置选项“Gui”,我希望选项 1 和选项 2 是必需的。
我尝试组合 MutuallyExclusiveSet 和 Required 属性,如下所示,但它并没有像我想象的那样工作。我是否误解了“MutuallyExclusiveSet”的概念或只是滥用它?还是图书馆还不支持的东西?
public class CommandLineOptions : CommandLineOptionsBase
[Option(null, "gui", Required = false, HelpText = "Launch the GUI", MutuallyExclusiveSet = "Gui")]
public bool Gui get; set;
[Option(null, "opt1", HelpText = "Option 1", MutuallyExclusiveSet = "CommandLine", Required = true)]
public string Option1 get; set;
[Option(null, "opt2", HelpText = "Option 2", MutuallyExclusiveSet = "CommandLine", Required = true)]
public string Option2 get; set;
【问题讨论】:
它的工作方式与您的预期相反,实际行为是什么? 如果我只传递“gui”并显示需要“opt1”的错误,则库无法解析参数。我希望它可以作为“gui”在不同的 MutuallyExclusiveSet 中工作。 【参考方案1】:属于互斥集合的所有选项在它们之间都是互斥的。 按照这个例子:
class Options
[Option("a", null, MutuallyExclusiveSet="zero")]
public string OptionA get; set;
[Option("b", null, MutuallyExclusiveSet="zero")]
public string OptionB get; set;
[Option("c", null, MutuallyExclusiveSet="one")]
public string OptionC get; set;
[Option("d", null, MutuallyExclusiveSet="one")]
public string OptionD get; set;
根据这些规则,以下命令行是有效的:
$ app -a foo -c bar
$ app -a foo -d bar
$ app -b foo -c bar
$ app -b foo -d bar
这些不是:
$ app -a foo -b bar
$ app -c foo -d bar
$ app -a foo -b bar -c foo1 -d foo2
如您所见,您不能同时指定属于同一集合的选项。还要记住,预构建的单例 (CommandLineParser.Default) 不适用于 MutualliyExclusiveSet 属性。你需要自己装一个解析器:
if (new CommandLineParser(new CommandLineParserSettings
MutuallyExclusive = true,
CaseSensitive = true,
HelpWriter = Console.Error).ParseArguments(args, opts)
// consume values here
Console.WriteLine(opts.OptionA);
这是命令行解析器库中互斥选项的工作方式。无论如何,为了解决您的特定问题,我建议您像在普通控制台应用程序中那样定义所有选项。然后添加 Gui 布尔开关。如果指定了此选项,则忽略其他选项。如果不是正常的控制台应用程序。
(另一件事:在后续版本中将有一个称为“子命令”的功能,它可以让您管理多个选项类型;这可能是这个即将推出的功能的正确情况。)
编辑 2015-08-30:
在 1.9.x 稳定版中实现的功能总是会造成混乱,默认情况下被禁用,需要开发人员通过设置实例激活它。
版本 2.0.x,内核被完全重写,该功能始终处于活动状态,我将尝试展示一个简单的示例(请记住,公共 API 已更改,因为 2.0.x 是主要版本更新)。
class Options
[Option(SetName = "web")]
public string WebUrl get; set;
[Option(SetName = "web")]
public int MaxLinks get; set;
[Option(SetName = "ftp")]
public string FtpUrl get; set;
[Option(SetName = "ftp")]
public int MaxFiles get; set;
[Option]
public bool Verbose get; set;
来自ftp
的集合与来自web
、--verbose
的集合不兼容(不属于集合,或者更好地属于默认集合,""
是中性的,可以在将要)。
有效:
$ app --weburl http://***.com --maxlinks 99
$ app --ftpurl ftp://ftp.myoffice.files.com --maxfiles 1234
$ app --verbose --weburl http://twitter.com --maxlinks 777
$ app --ftpurl ftp://ftp.xyz.org --maxfiles 44 --verbose
$ app --verbose
无效:
$ app --weburl http://***.com --maxlinks 99 --ftpurl ftp://ftp.xyz.org
$ app --ftpurl ftp://ftp.myoffice.files.com --maxfiles 1234 --maxlinks 777
$ app --verbose --weburl http://twitter.com --maxfiles 44
$ app --maxfiles 44 --maxlinks 99
【讨论】:
非常感谢您的详细解答!我感觉我误解了这个概念......我最终在我的选项类中添加了一个 Validate 函数来检查参数。在未来的功能可能解决这种情况之前,这将起到作用。 这与the wiki 所说的完全相反,但它看起来就是这样。 直到 2.0.* 成为stable
(现在是 beta
),wiki 的特定部分专门用于该新版本:github.com/gsscoder/commandline/wiki/Latest-Version。当它变得稳定时,一切都会更新。
@gsscoder 您的帖子仍然没有解释(至少对我而言)如何使用Required
和SetName
的组合。
@gsscoder 感谢您的回答。但是,即使使用 2.x 版,问题仍然存在,您不能将 Required
选项与 SetName 一起使用。假设我有一个FooSet
和一个BarSet
。现在,每当使用FooOption
时,我想通过用Required
装饰它来强制使用SecondFooOption
。现在我不能再使用BarSet
选项(即使没有使用FooSet
选项),因为解析失败是因为SecondFooOption
被修饰为Required
。以上是关于具有互斥必需参数的命令行解析器的主要内容,如果未能解决你的问题,请参考以下文章
parser.add_argument()用法——命令行选项参数和子命令解析器
[Python系列-25]:argparse --- 命令行选项参数解析器