尽管我通常使用Groovy编写要从命令行运行的JVM托管脚本,但是有时候我需要解析Java应用程序中的命令行参数,并且有很多库可供Java开发人员用来解析命令行参数。 在本文中,我将介绍这些Java命令行解析库中最著名的一种: Apache Commons CLI

我以前曾在Apache Commons CLI上发表过博客 ,但该文章已有八年历史,描述了Apache Commons CLI 1.1 自那以后,我在那篇文章中演示的两个类GnuParserPosixParser被弃用了。 本篇文章中的示例基于Apache Commons CLI 1.4,并使用CLI 1.3中引入的更新的DefaultParser来替代GnuParserPosixParser

Apache Commons CLI文档的“ 简介 ”介绍了Commons CLI如何完成“命令行处理的三个阶段”(“定义”,“解析”和“询问”)。 这三个阶段在Commons CLI中映射到OptionOptions类(“定义”), 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进行解析,而不是像旧代码中那样实例化PosxParserGnuParser

定义了命令行对象并解析了命令行之后,就该开始进行查询了。 下一个代码清单展示了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选项合适)。

下一个屏幕快照演示了简单示例的输出,该示例的代码清单如上所示,它们演示了对上述详细程度和文件路径/位置命令行选项的支持。

Java命令行界面(第1部分):Apache Commons CLI

当命令行参数不包含必需的命令行参数时,第二个屏幕快照演示了Commons CLI的输出。

Java命令行界面(第1部分):Apache 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);
}

Java命令行界面(第1部分):Apache Commons CLI

这篇文章演示了如何使用Apache Commons CLI实现与Java应用程序中的命令行解析有关的一些最常见功能,包括选项“定义”,命令行参数“解析”,解析后的命令行参数“查询”,以及与命令行参数相关的帮助/使用详细信息。 在选择框架或库来帮助使用Java进行命令行解析时,需要考虑以下Apache Commons CLI的其他特征。

对我来说,在简单Java应用程序中实现命令行界面时,Apache Commons CLI的最大优势之一就是我已经熟悉Groovy内置的CliBuilder用法 因为与基于Java的脚本相比,我更常将Groovy用于基于命令行的简单脚本和工具,所以对Groovy熟悉基本的Apache Commons CLI用法对返回Java很有帮助。

其他参考

翻译自: https://www.javacodegeeks.com/2017/06/java-command-line-interfaces-part-1-apache-commons-cli.html

相关文章: