虽然我通常使用 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(“解析”),以及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 实现的“Builder”模式具有构建器模式的优点,例如在一个语句中的完全完成状态,并使用高度可读的构建器方法来设置该实例的各个字段。我的关于 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 获取“usage”和“help”详细信息
/** * 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 的一些其他特性。
commons-cli-1.4.jar
) 的大小约为 53 MB。对我来说,在简单的 Java 应用程序中实现命令行界面时,Apache Commons CLI 的最大优势之一是我已经熟悉 Groovy 对 CliBuilder 的内置使用。因为与使用 Java 相比,我将 Groovy 更频繁地用于基于简单命令行的脚本和工具,因此对 Groovy 的基本 Apache Commons CLI 用法的熟悉在返回到 Java 时很有帮助。
其他参考资料
标签2: Java教程地址:https://www.cundage.com/article/jcg-java-command-line-interfaces-part-1-apache-commons-cli.html