尽管我通常使用Groovy编写要从命令行运行的JVM托管脚本,但是有时候我需要解析Java应用程序中的命令行参数,并且有很多库可供Java开发人员用来解析命令行参数。 在本文中,我将介绍这些Java命令行解析库中最著名的一种: Apache Commons CLI 。
我以前曾在Apache Commons CLI上发表过博客 ,但该文章已有八年历史,描述了Apache Commons CLI 1.1 。 自那以后,我在那篇文章中演示的两个类GnuParser和PosixParser被弃用了。 本篇文章中的示例基于Apache Commons CLI 1.4,并使用CLI 1.3中引入的更新的DefaultParser来替代GnuParser
和PosixParser
。
Apache Commons CLI文档的“ 简介 ”介绍了Commons CLI如何完成“命令行处理的三个阶段”(“定义”,“解析”和“询问”)。 这三个阶段在Commons CLI中映射到Option和Options类(“定义”), CommandLineParser接口(“ parsing”)和CommandLine类(“询问”)。
对于此处使用Apache Commons CLI构建的示例,预期的命令行参数相对简单。 一个参数是可选的,并且在指定时表示启用了详细输出。 另一个参数是必需的,用于指定虚构应用程序要处理的文件。 可选参数没有与该标志关联的值,并表示为-v
或--verbose
。 必需的参数后应跟一个值,该值是文件的路径和名称。 该标志是-f
或--file
。 下一个代码清单演示了如何使用Commons CLI的Option.Builder (由Commons CLI 1.3引入)来构建预期的选项,作为“定义”阶段的一部分。
在“定义阶段”使用Apache Commons CLI Option.Builder
示例
/*** "Definition" stage of command-line parsing with Apache Commons CLI.* @return Definition of command-line options.*/
private static Options generateOptions()
{final Option verboseOption = Option.builder("v").required(false).hasArg(false).longOpt(VERBOSE_OPTION).desc("Print status with verbosity.").build();final Option fileOption = Option.builder("f").required().longOpt(FILE_OPTION).hasArg().desc("File to be processed.").build();final Options options = new Options();options.addOption(verboseOption);options.addOption(fileOption);return options;
}
如上例所示,为Apache Commons CLI实现的“ 构建器 ”模式具有构建器模式的优点,例如在一条语句中以完全完成的状态创建Option
,并使用高度可读的构建器方法来设置该实例的各个字段。 我在Apache Commons CLI上的较旧文章演示了如何使用替代的传统构造方法实例化Option
实例。
定义了命令行选项之后,该进入“解析”阶段了,下一个代码清单演示了如何通过简单地调用方法CommandLinePaser.parse()来使用Apache Commons CLI进行解析。
使用Commons CLI解析命令行选项
/*** "Parsing" stage of command-line processing demonstrated with* Apache Commons CLI.** @param options Options from "definition" stage.* @param commandLineArguments Command-line arguments provided to application.* @return Instance of CommandLine as parsed from the provided Options and* command line arguments; may be {@code null} if there is an exception* encountered while attempting to parse the command line options.*/
private static CommandLine generateCommandLine(final Options options, final String[] commandLineArguments)
{final CommandLineParser cmdLineParser = new DefaultParser();CommandLine commandLine = null;try{commandLine = cmdLineParser.parse(options, commandLineArguments);}catch (ParseException parseException){out.println("ERROR: Unable to parse command-line arguments "+ Arrays.toString(commandLineArguments) + " due to: "+ parseException);}return commandLine;
}
请注意,此代码使用更新版本的Apache Commons CLI实例化DefaultParser
进行解析,而不是像旧代码中那样实例化PosxParser
或GnuParser
。
定义了命令行对象并解析了命令行之后,就该开始进行查询了。 下一个代码清单展示了Apache Commons CLI对命令行询问的支持。
使用Commons CLI询问命令行
final boolean verbose =commandLine.hasOption(VERBOSE_OPTION);
final String fileName =commandLine.getOptionValue(FILE_OPTION);
out.println("The file '" + fileName + "' was provided and verbosity is set to '" + verbose + "'.");
上面的代码清单演示了如何使用CommandLine.hasOption()来确定是否存在选项的特定标志,而无需考虑是否为该标志提供了值(在我们的示例中, -v
/ --verbose
是适当的)。 同样,代码显示CommandLine.getOptionValue()可用于获取与所提供的命令行标志关联的值(在我们的示例中, -f
/ --file
选项合适)。
下一个屏幕快照演示了简单示例的输出,该示例的代码清单如上所示,它们演示了对上述详细程度和文件路径/位置命令行选项的支持。
当命令行参数不包含必需的命令行参数时,第二个屏幕快照演示了Commons CLI的输出。
对于任何用于构建Java命令行解析的框架,有用的功能是支持使用和帮助信息的能力。 这是通过Commons CLI的HelpFormatter完成的。 下一个代码清单演示了如何使用HelpFormatter
来打印帮助和用法信息,并且代码清单后的屏幕快照演示了使用时的帮助和用法外观。
通过Commons CLI获取“用法”和“帮助”详细信息
/*** Generate usage information with Apache Commons CLI.** @param options Instance of Options to be used to prepare* usage formatter.* @return HelpFormatter instance that can be used to print* usage information.*/
private static void printUsage(final Options options)
{final HelpFormatter formatter = new HelpFormatter();final String syntax = "Main";out.println("\n=====");out.println("USAGE");out.println("=====");final PrintWriter pw = new PrintWriter(out);formatter.printUsage(pw, 80, syntax, options);pw.flush();
}/*** Generate help information with Apache Commons CLI.** @param options Instance of Options to be used to prepare* help formatter.* @return HelpFormatter instance that can be used to print* help information.*/
private static void printHelp(final Options options)
{final HelpFormatter formatter = new HelpFormatter();final String syntax = "Main";final String usageHeader = "Example of Using Apache Commons CLI";final String usageFooter = "See http://marxsoftware.blogspot.com/ for further details.";out.println("\n====");out.println("HELP");out.println("====");formatter.printHelp(syntax, usageHeader, options, usageFooter);
}
这篇文章演示了如何使用Apache Commons CLI实现与Java应用程序中的命令行解析有关的一些最常见功能,包括选项“定义”,命令行参数“解析”,解析后的命令行参数“查询”,以及与命令行参数相关的帮助/使用详细信息。 在选择框架或库来帮助使用Java进行命令行解析时,需要考虑以下Apache Commons CLI的其他特征。
- Apache Commons CLI是开源的,并获得了Apache License 2.0版的许可 。
- 当前版本的Apache Commons CLI( 1.4 )需要J2SE 5或更高版本。
- Apache Commons CLI不需要单独下载或引用任何第三方库 。
- Apache Commons CLI 1.4主JAR(
commons-cli-1.4.jar
)的大小约为53 MB。 - Apache Groovy通过CliBuilder基于Apache Commons CLI提供了现成的命令行解析功能。
- Maven资源库显示了对Apache Commons CLI(包括Apache Groovy)的 近1800种依赖 。
- Apache Commons CLI已经存在了一段时间。 它最初的1.0版本是在2002年11月。
对我来说,在简单Java应用程序中实现命令行界面时,Apache Commons CLI的最大优势之一就是我已经熟悉Groovy内置的CliBuilder用法 。 因为与基于Java的脚本相比,我更经常将Groovy用于基于命令行的简单脚本和工具,所以对Groovy熟悉基本的Apache Commons CLI用法对返回Java很有帮助。
其他参考
- Apache Commons CLI
- Apache Commons CLI简介
- Apache Commons CLI使用场景
- Apache Commons CLI API文档
- 使用Apache Commons CLI进行命令行解析 (我2008年在Apache Commons CLI上的帖子)
翻译自: https://www.javacodegeeks.com/2017/06/java-command-line-interfaces-part-1-apache-commons-cli.html