处理命令行参数的devise模式是什么?
如果您正在编写可从命令行执行的程序,则通常需要为用户提供多个选项或标志以及可能的多个参数。 我偶然发现了很多次,但是有什么样的devise模式可以循环使用参数并分离出适当的函数呢?
考虑:
myprogram -f filename -d directory -r regex
如何在使用您的语言的任何内置函数检索参数后组织代码? (语言特定的答案欢迎,如果这有助于你清楚地expression答案)
我不知道任何logging在案的“模式”的处理。
我相信处理参数的最古老的库/ API之一是getopt。 谷歌search“getopt”显示了很多手册页和实现的链接。
通常,我的应用程序中有一个首选项或设置服务,参数处理器知道如何与之通信。 然后参数被翻译成这个服务的东西,比应用程序的查询。 这可以像设置字典一样简单(比如名为“filename”的string设置)。
我认为以下答案更符合您所寻找的内容:
您应该看看应用模板模式(“devise模式”中的模板方法[Gamma,等])
简而言之,它的整体处理过程如下所示:
If the arguments to the program are valid then Do necessary pre-processing For every line in the input Do necessary input processing Do necessary post-processing Otherwise Show the user a friendly usage message
简而言之,实现一个ConsoleEngineBase类,该类具有以下方法:
PreProcess() ProcessLine() PostProcess() Usage() Main()
然后创build一个机箱,实例化一个ConsoleEngine()实例,并发送Main()消息来启动它。
要查看如何将其应用于控制台或命令行程序的一个很好的示例,请查看以下链接: http : //msdn.microsoft.com/zh-cn/magazine/cc164014.aspx
这个例子是在C#中,但是这些想法很容易在其他任何环境中实现。
你可以将GetOpt()看作适合参数处理(预处理)的部分。
希望这可以帮助。
你没有提到这个语言,但是对于Java而言,我们喜欢Apache Commons CLI 。 对于C / C ++,getopt。
对此有几点意见
首先,虽然本身没有任何模式,但编写parsing器本质上是一个机械练习,因为给定一个语法,可以很容易地生成一个parsing器。 像Bison和ANTLR这样的工具让人想起来。
也就是说,parsing器生成器通常是命令行的矫枉过正。 所以通常的模式是自己写(像其他人一样)几次,直到你厌倦了处理繁琐的细节,并find一个图书馆为你做。
我为C ++写了一个节省了一大堆getopt的工作,并且很好地使用了模板: TCLAP
那么,它是一个老职位,但我仍然愿意贡献。 这个问题的目的是selectdevise模式,但是我可以看到很多关于使用哪个库的讨论。 我已经检查了微软链接按照lindsay谈到模板devise模式使用。
但是,我不相信这个职位。 模板模式的意图是定义一个模板,将由各种其他类实现具有统一的行为。 我不认为parsing命令行适合它。
我宁愿用“Command”的devise模式去。 这种模式最适合菜单驱动的选项。
http://www.blackwasp.co.uk/Command.aspx
所以在你的情况下,-f,-d和-r全部成为具有共同或单独的接收机定义的命令。 这样可以在将来定义更多的接收器。 下一步将是链接这些命令的责任,以防需要处理链。 为此我会select。
http://www.blackwasp.co.uk/ChainOfResponsibility.aspx
我想这两个组合最好是组织命令行处理或任何菜单驱动的方法的代码。
boost :: program_options库是很好的,如果你在C ++中,并有使用Boost的豪华。
假设你有一个“configuration”对象,你的目标是设置标志和一个合适的命令行分析器,负责parsing命令行并提供一个固定的选项stream,这里是一个伪代码块
while (current_argument = cli_parser_next()) { switch(current_argument) { case "f": //Parser strips the dashes case "force": config->force = true; break; case "d": case "delete": config->delete = true; break; //So on and so forth default: printUsage(); exit; } }
我更喜欢“-t text”和“-i 44”等选项; 我不喜欢“-fname”或“–very-long-argument = some_value”。
而“ – ?”,“-h”和“/ h”都会产生一个帮助画面。
以下是我的代码的外观:
int main (int argc, char *argv[]) { int i; char *Arg; int ParamX, ParamY; char *Text, *Primary; // Initialize... ParamX = 1; ParamY = 0; Text = NULL; Primary = NULL; // For each argument... for (i = 0; i < argc; i++) { // Get the next argument and see what it is Arg = argv[i]; switch (Arg[0]) { case '-': case '/': // It's an argument; which one? switch (Arg[1]) { case '?': case 'h': case 'H': // A cry for help printf ("Usage: whatever...\n\n"); return (0); break; case 't': case 'T': // Param T requires a value; is it there? i++; if (i >= argc) { printf ("Error: missing value after '%s'.\n\n", Arg); return (1); } // Just remember this Text = Arg; break; case 'x': case 'X': // Param X requires a value; is it there? i++; if (i >= argc) { printf ("Error: missing value after '%s'.\n\n", Arg); return (1); } // The value is there; get it and convert it to an int (1..10) Arg = argv[i]; ParamX = atoi (Arg); if ((ParamX == 0) || (ParamX > 10)) { printf ("Error: invalid value for '%s'; must be between 1 and 10.\n\n", Arg); return (1); } break; case 'y': case 'Y': // Param Y doesn't expect a value after it ParamY = 1; break; default: // Unexpected argument printf ("Error: unexpected parameter '%s'; type 'command -?' for help.\n\n", Arg); return (1); break; } break; default: // It's not a switch that begins with '-' or '/', so it's the primary option Primary = Arg; break; } } // Done return (0); }
我正在用mes5k的ANTLR答案。 Codeproject的这个链接是为了讨论ANLTR并使用访问模式来实现你希望你应用的行为。 这是写得很好,值得回顾。
我会build议使用命令行处理器库。 一些俄罗斯人创造了一个体面的,但有他们在那里吨。 将节省您一些时间,以便您可以专注于您的应用程序的目的,而不是parsing命令行开关!
Getopt是唯一的出路。
你没有提到这个语言,但如果你正在寻找一个非常好的Objective-C包装getopt然后Dave Dribin的DDCLI框架是非常好的。
我在perl中使用了Getopts :: std和Getopts :: long ,并在C中使用Getopt函数。这标准化了参数的parsing和格式。 其他语言有不同的处理机制。
希望这可以帮助
标准devise通常遵循getopt的规定,许多语言都有getopt库,.NET,python,C,Perl,PHP等。
基本的devise是有一个命令行parsing器,该parsing器逐个返回循环中要检查的参数。
本文将对此进行更详细的讨论。
我对图书馆没什么兴趣,但这绝对有帮助。 作为一个例子,我正在寻找更多的“伪代码”来说明处理平均一堆标志和一堆更长的参数的过程。