如果您正在编写可从命令行执行的程序,您通常希望为用户提供多个选项或标志,以及可能的多个参数。我偶然发现了这么多次,但是有没有某种设计模式可以循环遍历args并调用适当的处理函数?
考虑:
myprogram -f filename -d directory -r regex
在使用语言的内置函数检索参数后,如何组织处理函数? (欢迎语言特定的答案,如果这有助于你明确答案)
答案 0 :(得分:15)
我认为以下答案更符合您的要求:
您应该考虑应用模板模式(“设计模式”[Gamma,el al]中的模板方法)
简而言之,整体处理如下:
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()
然后创建一个底层,实例化一个ConsoleEngine()实例并发送Main()消息以启动它。
要查看如何将其应用于控制台或命令行程序的一个很好的示例,请查看以下链接: http://msdn.microsoft.com/en-us/magazine/cc164014.aspx
示例在C#中,但这些想法很容易在任何其他环境中实现。
您可以将GetOpt()视为适合参数处理(预处理)的部分。
希望这有帮助。
答案 1 :(得分:14)
我不知道任何有关处理的文件“模式”。
我相信用于处理参数的最古老的库/ API之一是getopt。谷歌搜索“getopt”显示了很多手册页和实现链接。
通常,我的应用程序中有一个首选项或设置服务,参数处理器知道如何与之通信。然后将参数转换为此服务中的某个应用程序,而不是查询。这可以像设置字典一样简单(比如名为“filename”的字符串设置)。
答案 2 :(得分:5)
你没有提到这种语言,但对于Java我们很喜欢Apache Commons CLI。对于C / C ++,getopt。
答案 3 :(得分:4)
对此有一些评论...
首先,虽然本身没有任何模式,但编写解析器本质上是一种机械练习,因为给定语法,可以很容易地生成解析器。我想到了像Bison和ANTLR这样的工具。
也就是说,解析器生成器对于命令行来说通常是过度的。所以通常的模式是自己写一个(正如其他人已经证明的那样)几次,直到你厌倦了处理繁琐的细节并找到一个库为你做这件事。
我为C ++写了一篇文章,它节省了许多getopt赋予的功能并充分利用了模板:TCLAP
答案 4 :(得分:4)
嗯,这是一个老帖子,但我还是想贡献一下。这个问题的目的是选择设计模式,但我可以看到很多关于使用哪个库的讨论。我已经检查了lindsay的microsoft链接,它讨论了要使用的模板设计模式。
但是,我不相信这篇文章。模板模式的目的是定义一个模板,该模板将由各种其他类实现以具有统一的行为。我不认为解析命令行适合它。
我宁愿选择" Command"设计模式。此模式最适合菜单驱动选项。
http://www.blackwasp.co.uk/Command.aspx
所以在你的情况下,-f,-d和-r都变成了具有公共或单独接收器定义的命令。这样,将来可以定义更多的接收器。下一步将链接这些命令的责任,以防需要处理链。我会选择。
http://www.blackwasp.co.uk/ChainOfResponsibility.aspx
我想这两者的组合最好组织命令行处理或任何菜单驱动方法的代码。
答案 5 :(得分:2)
如果您使用C ++并且可以使用Boost,那么boost::program_options库很不错。
答案 6 :(得分:2)
假设您有一个“config”对象,您希望使用标志和一个合适的命令行解析器进行设置,该解析器负责解析命令行并提供一个常量的选项流,这里是一个伪代码块
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;
}
}
答案 7 :(得分:2)
我更喜欢“-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);
}
答案 8 :(得分:2)
我正在试着用mes5k回答ANTLR。此link to Codeproject适用于讨论ANLTR并使用访问模式实现您希望应用程序执行的操作的文章。它写得很好,值得回顾。
答案 9 :(得分:1)
我建议使用命令行处理器库。 Some Russian guy创造了一个体面的,但其中有很多。将节省您一些时间,以便您可以专注于应用程序的目的,而不是解析命令行开关!
答案 10 :(得分:1)
Getopt是唯一的出路。
答案 11 :(得分:1)
答案 12 :(得分:0)
你没有提到这种语言,但如果你正在寻找一个非常好的Objective-C包装器,那么Dave Dribin的DDCLI框架非常好。
答案 13 :(得分:0)
我在perl中使用Getopts::std和Getopts::long以及在C中使用Getopt函数。这标准化了参数的解析和格式。其他语言有不同的处理机制。
希望这有帮助
答案 14 :(得分:0)
标准设计通常遵循getopt所做的,有许多语言的getopt库,.NET,python,C,Perl,PHP等。
基本设计是有一个命令行解析器,它逐个部分地返回传递给循环中检查的参数。
This文章更详细地讨论了它。
答案 15 :(得分:-1)
我对图书馆并不感兴趣,但这绝对有帮助。我正在寻找一些“伪代码”,它说明了处理你的平均标志和一堆较长的参数,作为一个例子。