简单使用 Apache Commons CLI 库

CLI
本文将介绍怎样简单使用Apache Commons CLI 库解析命令行参数

以下部分描述了有关如何在应用程序中使用 CLI 的一些示例场景。

使用布尔选项

布尔选项在命令行上由该选项的存在表示,即,如果找到该选项,则该选项值为真,否则该值为假。

DateApp实用程序将当前日期打印到标准输出。

如果存在-t选项,还会打印当前时间。

创建 Options

必须创建一个Options对象,并且必须将该选项添加到该对象中。

// create Options object
Options options = new Options();

// add t option
options.addOption("t", false, "display current time");

addOption 方法有三个参数。第一个参数用来指定选项,类型为 java.lang.String。第二个参数是一个布尔值,它指定选项是否需要参数。如果参数是布尔选项(有时也称为标志参数),布尔选项是不存在参数的,因此第二个参数设置为 false。第三个参数是选项的描述,此描述信息将在应用程序的使用文本中显示。

解析命令行参数

CommandLineParser 的解析方法用于解析命令行参数。CommandLineParser 接口可能有几种实现,建议使用 DefaultParser。

CommandLineParser parser = new DefaultParser();
CommandLine cmd = parser.parse(options, args);

现在我们需要检查是否存在 t 选项。为此,我们将询问 CommandLine 对象。hasOption 方法接受一个 java.lang.String 类型参数,如果存在由 java.lang.String 表示的选项,则返回 true,否则返回 false。

if(cmd.hasOption("t")) {
    // 打印日期和时间
} else {
    // 打印日期
}

注意:

从 1.5 版开始,DefaultParser 类提供了 DefaultParser(final boolean allowPartialMatching) 构造函数,它的 allowPartialMatching 参数用来开启/禁用部分匹配。如以下代码:

final Options options = new Options();
options.addOption(new Option("d", "debug", false, "Turn on debug."));
options.addOption(new Option("e", "extract", false, "Turn on extract."));
options.addOption(new Option("o", "option", true, "Turn on option with argument."));

如果开启了 “部分匹配” 后(即 allowPartialMatching=true),-de 参数只匹配 “debug” 选项。如果在禁用 “部分匹配” (即 allowPartialMatching=false)的情况下,-de 将同时启用调试(debug)和提取(extract)选项。

国际时间

InternationalDateApp 实用程序通过提供打印世界上任何国家/地区的日期和时间的功能扩展了 DateApp 实用程序。为方便起见,引入了一个新的命令行选项 c。代码如下:

// add c option
options.addOption("c", true, "country code");

第二个参数这次为 true。这里指定 c 选项需要一个参数值。如果在命令行上指定了必需的选项参数值,则返回该参数值。否则返回 null。

检索参数值

CommandLine 的 getOptionValue() 方法用于检索选项的参数值。代码如下:

// 获取 c 选项值
String countryCode = cmd.getOptionValue("c");

if(countryCode == null) {
    // 打印默认日期
} else {
    // 打印由国家代码指定的国家/地区的日期
}

以Ant为例

这里将使用 Ant 来说明如何创建所需的选项,以下是Ant的帮助输出。

ant [options] [target [target2 [target3] ...]]
  Options: 
  -help                  print this message
  -projecthelp           print project help information
  -version               print the version information and exit
  -quiet                 be extra quiet
  -verbose               be extra verbose
  -debug                 print debugging information
  -emacs                 produce logging information without adornments
  -logfile <file>        use given file for log
  -logger <classname>    the class which is to perform logging
  -listener <classname>  add an instance of class as a project listener
  -buildfile <file>      use given buildfile
  -D<property>=<value>   use value for given property
  -find <file>           search for buildfile towards the root of the
                         filesystem and use it

定义布尔选项

让我们为应用程序创建布尔选项,因为它们最容易创建。为清楚起见,此处使用了 Option 的构造函数。

Option help = new Option("help", "print this message");
Option projecthelp = new Option("projecthelp", "print project help information");
Option version = new Option("version", "print the version information and exit");
Option quiet = new Option("quiet", "be extra quiet");
Option verbose = new Option("verbose", "be extra verbose");
Option debug = new Option("debug", "print debugging information");
Option emacs = new Option("emacs", "produce logging information without adornments");

定义参数选项

参数选项是使用 Option#Builder 创建的。

Option logfile   = Option.builder("logfile")
                         .argName("file")
                         .hasArg()
                         .desc("use given file for log")
                         .build();

Option logger    = Option.builder("logger")
                         .argName("classname")
                         .hasArg()
                         .desc("the class which it to perform logging")
                         .build();

Option listener  = Option.builder("listener")
                         .argName("classname")
                         .hasArg()
                         .desc("add an instance of class as "
                                + "a project listener")
                         .build();

Option buildfile = Option.builder("buildfile")
                         .argName("file")
                         .hasArg()
                         .desc("use given buildfile")
                         .build();

Option find      = Option.builde("find")
                         .argName("file")
                         .hasArg()
                         .desc("search for buildfile towards the "
                                + "root of the filesystem and use it")
                         .build();

定义 Java 属性选项

要创建的最后一个选项是 Java 属性,它也是使用 OptionBuilder 创建的。

Option property  = Option property  = Option.builder("D")
                                .hasArgs()
                                .valueSeparator('=')
                                .build();

稍后可以通过在 CommandLine 上调用 getOptionProperties("D") 方法来检索此选项指定的属性映射。

创建选项

现在我们已经创建了每个选项,我们需要创建选项实例。这是使用 Options 的 addOption 方法实现的。

Options options = new Options();
options.addOption(help);
options.addOption(projecthelp);
options.addOption(version);
options.addOption(quiet);
options.addOption(verbose);
options.addOption(debug);
options.addOption(emacs);
options.addOption(logfile);
options.addOption(logger);
options.addOption(listener);
options.addOption(buildfile);
options.addOption(find);
options.addOption(property);

所有的准备工作现在已经完成,我们现在准备解析命令行参数。

创建 Parser

我们现在需要创建一个 CommandLineParser。这将使用选项指定的规则解析命令行参数,并返回一个 CommandLine 实例。

public static void main(String[] args) {
    // create the parser
    CommandLineParser parser = new DefaultParser();
    try {
        // parse the command line arguments
        CommandLine line = parser.parse(options, args);
    }
    catch (ParseException exp) {
        // oops, something went wrong
        System.err.println("Parsing failed.  Reason: " + exp.getMessage());
    }
}

查询命令行

要查看是否已传递选项,请使用 hasOption 方法。可以使用 getOptionValue 方法检索参数值。

// 是否指定了 buildfile 参数?
if(line.hasOption("buildfile")) {
    // initialise the member variable
    this.buildfile = line.getOptionValue("buildfile");
}

显示用法和帮助

CLI 还提供了自动生成使用和帮助信息的方法。这是通过 HelpFormatter 类实现的。

// 自动生成帮助说明
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp("ant", options);

执行时会产生以下输出:

usage: ant
-D <property=value>     use value for given property
-buildfile <file>       use given buildfile
-debug                  print debugging information
-emacs                  produce logging information without adornments
-file <file>            search for buildfile towards the root of the
                        filesystem and use it
-help                   print this message
-listener <classname>   add an instance of class as a project listener
-logger <classname>     the class which it to perform logging
-projecthelp            print project help information
-quiet                  be extra quiet
-verbose                be extra verbose
-version                print the version information and exit

如果您还需要打印使用说明,则调用 formatter.printHelp("ant", options, true) 将生成使用说明以及帮助信息。

创建 ls 示例

Linux/Unix 世界中使用最广泛的命令行应用程序之一是 ls。由于 ls 需要大量选项,本示例仅涵盖一小部分选项。以下是输出的一部分帮助信息:

Usage: ls [OPTION]... [FILE]...
List information about the FILEs (the current directory by default).
Sort entries alphabetically if none of -cftuSUX nor --sort.

-a, --all                  do not hide entries starting with .
-A, --almost-all           do not list implied . and ..
-b, --escape               print octal escapes for non-graphic characters
    --block-size=SIZE      use SIZE-byte blocks
-B, --ignore-backups       do not list implied entries ending with ~
-c                         with -lt: sort by, and show, ctime (time of last
                           modification of file status information)
                           with -l: show ctime and sort by name
                           otherwise: sort by ctime
-C                         list entries by columns

以下是用于为此示例创建选项的代码:

// 创建命令行解析器
CommandLineParser parser = new DefaultParser();

// 创建 Options
Options options = new Options();
options.addOption("a", "all", false, "do not hide entries starting with .");
options.addOption("A", "almost-all", false, "do not list implied . and ..");
options.addOption("b", "escape", false, "print octal escapes for non-graphic "
                                         + "characters");
options.addOption(Option.builder("SIZE").longOpt("block-size")
                                .desc("use SIZE-byte blocks")
                                .hasArg()
                                .build());
options.addOption("B", "ignore-backups", false, "do not list implied entries "
                                                 + "ending with ~");
options.addOption("c", false, "with -lt: sort by, and show, ctime (time of last " 
                               + "modification of file status information) with "
                               + "-l:show ctime and sort by name otherwise: sort "
                               + "by ctime");
options.addOption("C", false, "list entries by columns");

String[] args = new String[]{ "--block-size=10" };

try {
    // 解析命令行参数
    CommandLine line = parser.parse(options, args);

    // 验证是否设置了 block-size 选项
    if (line.hasOption("block-size")) {
        // 打印 block-size 选项的值
        System.out.println(line.getOptionValue("block-size"));
    }
} catch (ParseException exp) {
    System.out.println("Unexpected exception:" + exp.getMessage());
}
最灵繁的人也看不见自己的背脊。——非洲
0 不喜欢
说说我的看法 -
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号