使用 Apache Commons CLI 来解析命令行参数

入门

介绍

命令行处理有三个阶段。它们是定义,解析和审讯阶段。

定义

每个命令行必须定义将用于定义应用程序接口的选项集。

CLI使用Options类作为Option实例的容器 。
在CLI中有两种方法可以创建Option。其中一个是通过构造函数,另一个是通过Options中定义的工厂方法 。

定义阶段的结果是Options实例。

解析

解析阶段是处理通过命令行传递到应用程序的文本的位置。根据解析器实现定义的规则处理文本。

在CommandLineParser上定义的parse方法接受一个Options 实例和一个String[]参数,并返回一个CommandLine。

若输入的选项及参数不符合定义的规则,则抛出ParseException,我们可以捕获它,并进行处理。解析阶段的结果是CommandLine实例。

审讯

审讯阶段是应用程序查询CommandLine以根据布尔选项决定要执行的执行分支并使用选项值来提供应用程序数据的位置。

此阶段在用户代码中实现。CommandLine上的访问器方法为用户代码提供了询问功能。

审讯阶段的结果是用户代码完全了解在命令行上提供的所有文本,并根据解析器和选项规则进行处理。

示例

问题描述

wc -c -l -w -o out.txt in.txt -h(–help)

wc是一个可执行程序,它可以统计一个文本文件的字符数、单词数和行数

先来规定一些词汇,-o我们称它为选项(option),它的参数(arg)是out.txt;-c也是一个选项,它没有参数值;in.txt是一个参数值,它没有选项名

in.txt 输入文件名,必选(在需要统计的时候,如果只需要打印帮助,如 wc -h ,则不需要文件名)

-o out.txt 输出文件名,可选,若不指定,则默认输出到result.txt,但不能单独使用

-c 统计字符数

-l 统计行数

-w 统计单词数

-c,-l,-w 三个参数都是可选的

-h选择打印帮助,可选,特殊的是,它还有一个对应的长选项,–help

多个单参数可放置在一个-后面,如-clw

参数的位置不确定,可随意放置

若什么参数都没输入,则打印帮助(参数输入规则)

定义规则

Options options = new Options();
/*
 * 我使用全包含构造方法来实例化option,以便看到它的所有参数
 * 
 * 构造函数原型为:
 * 
 * public Option(String opt, String longOpt, boolean hasArg, String description)
 * throws ...
 * 
 * opt为短选项名,如h;longOpt为长选项名,如help;
 * 
 * hasArg为是否有参数值,-w不需要参数值,而-o需要参数值,description为对该选项的描述
 */
Option chars = new Option("c", null, false, "统计字符数");

// 不需要设置长选项名
Option words = new Option("w", false, "统计单词数");

// 不设置hasArg,默认为false
Option lines = new Option("l", "统计行数");

/*
 * 你可能会感到奇怪,全包含构造方法怎么就四个参数,没错,它就是这样的
 * 
 * 在面向对象的方法中,四个参数已经算是很多了,太多的参数很容易把人搞晕的
 * 
 * 如果我们需要更复杂的构造方法,那么就要使用Builder来完成了,Option类有一个内部类Builder
 */
Option help = Option.builder("h").longOpt("help").hasArg(false).required(false).desc("帮助").build();

Option outFileName = Option.builder("o").hasArgs().argName("输出文件名").numberOfArgs(1).required(false)
		.desc("指定结果输出文件").build();

/*
 * 在以上的参数中,我并没有定义是不是必需的,它们都是非必需的
 * 
 * 因为程序有两种使用场景,只使用h参数,或者做统计工作
 * 
 * 在一种情况下的必需参数,可能到另一种情况下就不是必需的了
 */

options.addOption(chars);
options.addOption(words);
options.addOption(lines);
options.addOption(outFileName);
options.addOption(help);

return options;

解析参数

CommandLine commandLine = null;
try {
	/*
	 * 最新版本1.4(至少在我写这篇博客时,这是最新的版本)只有一个解析类可用,其它解析类已经被弃置
	 * 
	 * 看一下parse的全包含方法
	 * 
	 * public CommandLine parse(Options options, String[] arguments, Properties
	 * properties, boolean stopAtNonOption) throws ParseException
	 * 
	 * options为定义的规则;arguments为传入的参数;
	 * 
	 * properties为
	 * 
	 * stopAtNonOption 如果为真,未识别的参数将停止解析,剩余的参数将添加到返回的CommandLine的args列表中。
	 * 
	 * 如果为false,未识别的参数将触发ParseException
	 */
	commandLine = new DefaultParser().parse(options, args);
} catch (ParseException e) {
	System.out.println("[error] " + e.getMessage());
	System.exit(0);
}
return commandLine;

根据CommandLine来确定要执行哪些工作

if (hasOption("h") || hasOption("help")) {
	util.printHelp();
	System.exit(0);
}

if (checkArgWithoutOption()) {
	String inputFileName = getInputFileName();
}

if (hasOption("o")) {
	String outputFileName = getOptionValue("o");
}

if (hasOption("c")) {

}
if (hasOption("w")) {

}
if (hasOption("l")) {

}
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐