Apache Commons CLI官方文档翻译 —— 快速构建命令行启动模式

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介:

昨天通过几个小程序以及Hangout源码学习了CLI的基本使用,今天就来尝试翻译一下CLI的官方使用手册。
下面将会通过几个部分简单的介绍CLI在应用中的使用场景。

昨天已经联系过几个基本的命令行参数使用场景,可以参考这里

通过使用Apache Commons CLI可以帮助开发者快速构建命令行启动模式,并可以快速生成帮助指令,基于用户启动参数提供不同的服务。

入门样例

下面就举个例子,比如我想输入命令:

xxx -t

从而打印出当前的时间。

定义阶段——创建选项

首先要创建Options对象,然后添加Option对象.

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

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

其中addOption方法有三个参数:

  • 第一个参数是字符串类型,代表命令的参数。
  • 第二个参数是Bool型,代表该选项是否需要额外的参数。
  • 第三个参数是该选项的描述信息。

上面的例子就代表,t选项不需要参数,它的意思是显示当前时间

解析阶段——解析命令行参数

CLI通过CommandLineParser的parse方法解析命令行参数。有好几种CommandLineParser的实现类,推荐使用的是DefaultParser。看源码除了这个DefaultParser,其他的都被打上了@Deprecated标记
除去这个DefaultParser以外,还有一个抽象类实现了CommandLineParser接口——Parser,这个Parser有三个子类:

  • BasicParser
  • GnuParser
  • PosixParser
CommandLineParser parser = new DefaultParser();
CommandLine cmd = parser.parse( options, args);

询问阶段—— 判断命令行中出现了哪个选项

现在就可以检查是否存在这个t选项了,首先需要在CommandLine对象中进行查询。hasOption方法可以通过选项的名字,判断命令行是否出现该命令。出现则返回true,否则返回false。

if(cmd.hasOption("t")) {
    // print the date and time
}
else {
    // print the date
}

全部代码

public class DateApp {
    public static void main(String[] args) {
        String[] arg = {"-t"};
//      String[] arg = {};
        try {
            testOption(arg);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
    static void testOption(String[] args) throws ParseException{
        Options options = new Options();
        options.addOption("t", false, "display current time");
        
        CommandLineParser parser = new DefaultParser();
        CommandLine cmd = parser.parse( options, args);
        
        if(cmd.hasOption("t")) {
            System.out.println((new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(new Date()));
        }else {
            System.out.println((new SimpleDateFormat("yyyy-MM-dd")).format(new Date()));
        }
    }
}

进阶样例

下面这个例子继承自DateApp,并且提供了根据城市显示时间和日期的功能。为了实现这个命令,会增加一个c选项,来添加城市信息。

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

第二个参数这时设置为true,就代表它需要额外的参数。

获得参数值

CommandLine对象的getOptionValue方法可以获取到参数的值。

// get c option value
String countryCode = cmd.getOptionValue("c");

if(countryCode == null) {
    // print default date
}else {
    // print date for country specified by countryCode
}

此时如果只有c选项,没有参数,就会报错

org.apache.commons.cli.MissingArgumentException: Missing argument for option: c
    at org.apache.commons.cli.DefaultParser.checkRequiredArgs(DefaultParser.java:211)
    at org.apache.commons.cli.DefaultParser.parse(DefaultParser.java:125)
    at org.apache.commons.cli.DefaultParser.parse(DefaultParser.java:76)
    at org.apache.commons.cli.DefaultParser.parse(DefaultParser.java:60)
    at hangout.study.InternationalDateApp.testOption(InternationalDateApp.java:29)
    at hangout.study.InternationalDateApp.main(InternationalDateApp.java:18)

全部代码

public class InternationalDateApp {
    public static void main(String[] args) {
        String[] arg = {"-t","-c","hello"};
//      String[] arg = {"-t","-c"};
//      String[] arg = {};
        try {
            testOption(arg);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
    static void testOption(String[] args) throws ParseException{
        Options options = new Options();
        options.addOption("t", false, "display current time");
        options.addOption("c", true, "country code");
        
        CommandLineParser parser = new DefaultParser();
        CommandLine cmd = parser.parse( options, args);
        
        if(cmd.hasOption("t")) {
            System.out.println((new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(new Date())+" in "+cmd.getOptionValue("c"));
        }else {
            System.out.println((new SimpleDateFormat("yyyy-MM-dd")).format(new Date()));
        }
    }
}

此时运行代码,则会正确输出信息:

2016-06-23 21:18:50 in hello

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

使用Bool选项创建

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" );

也可以使用OptionBuilder构建选项:

Option logfile   = OptionBuilder.withArgName( "file" )
       .hasArg()
       .withDescription(  "use given file for log" )
       .create( "logfile" );

Option logger    = OptionBuilder.withArgName( "classname" )
       .hasArg()
       .withDescription( "the class which it to perform "+ "logging" )
       .create( "logger" );

Option listener  = OptionBuilder.withArgName( "classname" )
       .hasArg()
       .withDescription( "add an instance of class as "+ "a project listener" )
       .create( "listener"); 

Option buildfile = OptionBuilder.withArgName( "file" )
       .hasArg()
       .withDescription(  "use given buildfile" )
       .create( "buildfile");

Option find      = OptionBuilder.withArgName( "file" )
       .hasArg()
       .withDescription( "search for buildfile towards the "+ "root of the filesystem and use it" )
       .create( "find" );

最后一个OptionBuilder创建带有参数名称的选项:

Option property  = OptionBuilder.withArgName( "property=value" )
                                .hasArgs(2)
                                .withValueSeparator()
                                .withDescription( "use value for given property" )
                                .create( "D" );

通过上面的方式定义的属性,可以通过CommandLine对象的getOptionProperties("D")方法获得。

定义阶段——创建选项

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 );

解析阶段——创建解析器

跟前面类似,创建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选项判断是否包含某个选项参数:

// has the buildfile argument been passed?
if( line.hasOption( "buildfile" ) ) {
    // initialise the member variable
    this.buildfile = line.getOptionValue( "buildfile" );
}

创建帮助信息

一般命令行工具都有help帮助提示,即输入-h命令,就会输出所有的命令参数。CLI提供给我们快捷输出帮助信息的工具——HelpFormatter。

// automatically generate the help statement
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

全部代码

public class AntExample {
    public static void main(String[] args) {
        String[] arg = {"-help"};
        testOption(arg);
    }
    @SuppressWarnings({ "deprecation", "static-access" })
    static void testOption(String[] args){
        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 logfile   = OptionBuilder.withArgName( "file" )
                .hasArg()
                .withDescription(  "use given file for log" )
                .create( "logfile" );

        Option logger    = OptionBuilder.withArgName( "classname" )
                .hasArg()
                .withDescription( "the class which it to perform "+ "logging" )
                .create( "logger" );

        Option listener  = OptionBuilder.withArgName( "classname" )
                .hasArg()
                .withDescription( "add an instance of class as "+ "a project listener" )
                .create( "listener"); 

        Option buildfile = OptionBuilder.withArgName( "file" )
                .hasArg()
                .withDescription(  "use given buildfile" )
                .create( "buildfile");

        Option find = OptionBuilder.withArgName( "file" )
                .hasArg()
                .withDescription( "search for buildfile towards the " + "root of the filesystem and use it" )
                .create( "find" );
        Option property  = OptionBuilder.withArgName( "property=value" )
                .hasArgs(2)
                .withValueSeparator()
                .withDescription( "use value for given property" )
                .create( "D" );
        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 );
        
        CommandLineParser parser = new DefaultParser();
        try {
            CommandLine line = parser.parse( options, args );
            if( line.hasOption( "buildfile" ) ) {
               System.out.println(line.getOptionValue( "buildfile" ));
            }
            if( line.hasOption("help")){
                HelpFormatter formatter = new HelpFormatter();
                formatter.printHelp( "ant", options );
            }
        }catch( ParseException exp ) {
            System.err.println( "Parsing failed.  Reason: " + exp.getMessage() );
        }
    }
}

运行后得到下面的输出信息:

usage: ant
 -buildfile <file>       use given buildfile
 -D <property=value>     use value for given property
 -debug                  print debugging information
 -emacs                  produce logging information without adornments
 -find <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
 -logfile <file>         use given file for log
 -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

如果想在输出信息中加入参数列表,也可以在printHelp加入第三个参数true,formatter.printHelp( "ant", options, true);

usage: ant [-buildfile <file>] [-D <property=value>] [-debug] [-emacs]
       [-find <file>] [-help] [-listener <classname>] [-logfile <file>]
       [-logger <classname>] [-projecthelp] [-quiet] [-verbose] [-version]
 -buildfile <file>       use given buildfile
 -D <property=value>     use value for given property
 -debug                  print debugging information
 -emacs                  produce logging information without adornments
 -find <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
 -logfile <file>         use given file for log
 -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

LS样例

这个例子模拟了Linux下的命令行使用帮助:

全部代码:

public class LSExample {
    public static void main(String[] args) {
        String[] arg = new String[]{ "--block-size=10" };
        testOption(arg);
    }
    static void testOption(String[] args){
        CommandLineParser parser = new DefaultParser();

        // create the 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 nongraphic "
                                                 + "characters" );
        options.addOption( OptionBuilder.withLongOpt( "block-size" )
                                        .withDescription( "use SIZE-byte blocks" )
                                        .hasArg()
                                        .withArgName("SIZE")
                                        .create() );
        options.addOption( "B", "ignore-backups", false, "do not list implied entried "
                                                         + "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" );

        

        try {
            CommandLine line = parser.parse( options, args );

            if( line.hasOption( "block-size" ) ) {
                System.out.println( line.getOptionValue( "block-size" ) );
            }
        }
        catch( ParseException exp ) {
            System.out.println( "Unexpected exception:" + exp.getMessage() );
        }
    }
}

输出可以得到下面的信息:

10
usage: ls
 -a,--all                 do not hide entries starting with .
 -A,--almost-all          do not list implied . and ..
 -b,--escape              print octal escapes for nongraphic characters
 -B,--ignore-backups      do not list implied entried ending with ~
    --block-size <SIZE>   use SIZE-byte blocks
 -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

参考

我的前一天总结
Apache Common CLI官方文档

本文转自博客园xingoo的博客,原文链接:Apache Commons CLI官方文档翻译 —— 快速构建命令行启动模式,如需转载请自行联系原博主。
相关文章
|
5月前
|
存储 关系型数据库 Apache
Halodoc使用Apache Hudi构建Lakehouse的关键经验
Halodoc使用Apache Hudi构建Lakehouse的关键经验
72 4
|
5月前
|
存储 分布式计算 数据管理
基于 Apache Hudi + dbt 构建开放的Lakehouse
基于 Apache Hudi + dbt 构建开放的Lakehouse
97 3
|
5月前
|
消息中间件 存储 关系型数据库
使用Apache Hudi构建下一代Lakehouse
使用Apache Hudi构建下一代Lakehouse
55 0
|
2月前
|
消息中间件 监控 数据挖掘
基于RabbitMQ与Apache Flink构建实时分析系统
【8月更文第28天】本文将介绍如何利用RabbitMQ作为数据源,结合Apache Flink进行实时数据分析。我们将构建一个简单的实时分析系统,该系统能够接收来自不同来源的数据,对数据进行实时处理,并将结果输出到另一个队列或存储系统中。
108 2
|
11天前
|
存储 分布式计算 分布式数据库
深入理解Apache HBase:构建大数据时代的基石
在大数据时代,数据的存储和管理成为了企业面临的一大挑战。随着数据量的急剧增长和数据结构的多样化,传统的关系型数据库(如RDBMS)逐渐显现出局限性。
62 12
|
2月前
|
Java 持续交付 项目管理
Maven是一款基于Apache许可的项目管理和构建自动化工具,在Java开发中极为流行。
Maven是一款基于Apache许可的项目管理和构建自动化工具,在Java开发中极为流行。它采用项目对象模型(POM)来描述项目,简化构建流程。Maven提供依赖管理、标准构建生命周期、插件扩展等功能,支持多模块项目及版本控制。在Java Web开发中,Maven能够自动生成项目结构、管理依赖、自动化构建流程并运行多种插件任务,如代码质量检查和单元测试。遵循Maven的最佳实践,结合持续集成工具,可以显著提升开发效率和项目质量。
41 1
|
4月前
|
消息中间件 存储 Java
深度探索:使用Apache Kafka构建高效Java消息队列处理系统
【6月更文挑战第30天】Apache Kafka是分布式消息系统,用于高吞吐量的发布订阅。在Java中,开发者使用Kafka的客户端库创建生产者和消费者。生产者发送序列化消息到主题,消费者通过订阅和跟踪偏移量消费消息。Kafka以持久化、容灾和顺序写入优化I/O。Java示例代码展示了如何创建并发送/接收消息。通过分区、消费者组和压缩等策略,Kafka在高并发场景下可被优化。
107 1
|
4月前
|
Java 数据库连接 Apache
深入理解Apache Commons Pool2池化技术
深入理解Apache Commons Pool2池化技术
|
4月前
|
SQL 存储 运维
网易游戏如何基于阿里云瑶池数据库 SelectDB 内核 Apache Doris 构建全新湖仓一体架构
随着网易游戏品类及产品的快速发展,游戏数据分析场景面临着越来越多的挑战,为了保证系统性能和 SLA,要求引入新的组件来解决特定业务场景问题。为此,网易游戏引入 Apache Doris 构建了全新的湖仓一体架构。经过不断地扩张,目前已发展至十余集群、为内部上百个项目提供了稳定可靠的数据服务、日均查询量数百万次,整体查询性能得到 10-20 倍提升。
网易游戏如何基于阿里云瑶池数据库 SelectDB 内核 Apache Doris 构建全新湖仓一体架构
|
5月前
|
应用服务中间件 网络安全 Apache
构建高性能Web服务器:Nginx vs Apache
【5月更文挑战第16天】Nginx与Apache是两种主流Web服务器,各具优势。Nginx以其轻量级、高并发处理能力和反向代理功能见长,适合大型网站和高并发场景;而Apache以功能丰富、稳定性强闻名,适合企业网站和需要多种Web服务功能的场景。在性能上,Nginx处理高并发更优,Apache则可能在高负载时遭遇瓶颈。在选择时,应根据实际需求权衡。

推荐镜像

更多
下一篇
无影云桌面