• Apache Commons CLI


    简单的说,就是对命令的参数进行定义和解析的工具 -- 这里说的参数是我们常用的说法,而CLI里则是Option、Options,参数值(如果有)则是Option的arg(s)。


    ## 为什么

    那么,为什么要用这个工具呢?

    因为在很多情况下,一个命令要包含很多参数及值,而有时候我们又需要生成这样的参数,或者获解析这样的参数。

    如果使用字符串的切割或者正则来做,当然也不是不行,就是麻烦,特别是在参数顺序不定,参数值个数不定,参数和参数值的分隔符不定的时候,无疑是很令人头疼的一件事。

    这个时候,就是轮到CLI出马了。


    ## 概念

    CLI这个库很简单,1.3.1版本 只有22个Java文件,其中5个还是@Deprecated 。

    需要掌握的概念 Options、Option、CommandLineParser、CommandLine、HelpFormatter。


    以shell命令 “ls -l -a -w=5” 为例:

    CLI概念对应
    CommandLine “-l -a -w=5”
    Option “-l”或”-a”或”-w”或”-S”或其他
    Options “-l”、”-a”、”-w”、”-S”等所有Option的集合


    需要注意:

    CommandLine 不包含 ”ls” 本身。

    Option 有的是必选项,有的是可选项。

    Option 有的是带有值的,如”-w”,其值在Option中叫arg,而arg又有可选/必需之分,一些参数还有个数的限制。


    OK,基本概念就这么简单,进入代码阶段。

    ## Option

    Option的创建有两种方式,使用构造器,或者使用Option.builder。

    构造器方式如下:

    // 最简单的构造:参数名、参数说明
    Option option1 = new Option("-l", "长格式名字");
    
    // 参数名、参数是否有值、参数说明
    Option option2 = new Option("-a", false, "显示全部文件、文件夹");
            
    // 参数名、长参数名、参数是否有值、参数说明
    Option option3 = new Option("-C", "--color", true, "什么时候彩色输出,候选值always、never、auto");

    Option.builder 方式如下:

    Option optionColor = Option.builder("-C") //注意,不要漏掉"-"
                             .longOpt("--color") // 完整写法
                             .argName("颜色")
                             .desc("彩色输出设置")
                             .required(false) //该选项是否必需?
                             .hasArg(true) //该选项是否需要一个参数?因为有的选项不需要参数
                             .valueSeparator('=') //选项与参数连接的符号  -C=never
                             .numberOfArgs(1) //该选项最多能接收的参数
                             .optionalArg(false) //该选项的参数是否可选? 注意与required的区别
                             .type(String.class) //该选项的值的类型?
                             .build();

    可以看出,builder方式更全面一些,当然,最终生成的Option对象都是可以再逐项修改的。


    ## Options

    有了各个Option,就可以将其添加到Options中了。

    Options options = new Options();
    options.addOption(option); //将所有相关的Option都添加到Options中。


    ## CommandLineParser

    有了Options,我们就有了限制条件,就可以对实际的参数进行解析了。

    String[] args = {"-l", "-C=auto", "-w=5"}; //模拟。通常是获取到的,所以才需要解析。
    CommandLine commandLine = commandLineParser.parse(options, args);


    ## CommandLine

    拿到了CommandLine,我们就可以获取需要的参数及值了!

    // 可以获取到指定参数的值
    System.out.println(commandLine.getOptionValue("-a"));
    System.out.println(commandLine.getOptionValue("-C"));
    System.out.println(commandLine.getOptionValue("-w"));
    
    // 还可以判断是否存在某个参数,等等,略。


    OK,至此 其实已经撸完了必需的功能,着急的话就已经可以开工了。

    但是,CLI 还提供了两个小东西,很有意思的小东西:PatternOptionBuilder、HelpFormatter。


    ## PatternOptionBuilder

    这是一个快速构建Options的工具类,约定了一些符号的用法,如”:”、”/”、”!”等。

    Overview of PatternOptionBuilder patterns
    a-a flag
    b@-b [classname]
    c>-c [filename]
    d+-d [classname] (creates object via empty constructor)
    e%-e [number] (creates Double/Long instance depending on existing of a '.')
    f/-f [url]
    g:-g [string]

    注意,上面的字母都是参数项,这里只能使用单个字母。

    看例子吧:

    // 快速构建一个Options,有三个参数 "-v"、"-p"、"-f",其中"-p"需要有参数值,且类型是字符串;"-f"不是必选项,其参数值为URL
    Options options = PatternOptionBuilder.parsePattern("vp:!f/");
    
    // 参数,其实获取到的参数都是line.split("\s+"),就是字符串数组
    String[] args = {"-v", "-p", "whereru", "-f", "http://www.baidu.com"};
    
    CommandLine commandLine = commandLineParser.parse(options, args);
    
    System.out.println(commandLine.getOptionValue("v"));
    System.out.println(commandLine.getOptionValue("p"));
    System.out.println(commandLine.getOptionValue("f"));

    怎么样,够简单吧


    ## HelpFormatter

    这个工具类,顾名思义,就是格式化帮助信息用的。

    不多说,运行下一下下面的代码就明白了:

    // 输出命令的帮助信息(类似于shell中的 cmd --help的结果)
    @Test
    public void help(){
        HelpFormatter helpFormatter = new HelpFormatter();
    
        // 注意,下面这些setter都可以忽略
        helpFormatter.setSyntaxPrefix(">>>");
        helpFormatter.setArgName("参数的名字");
        helpFormatter.setLeftPadding(4);
        helpFormatter.setDescPadding(4);
        helpFormatter.setOptPrefix("-");
        helpFormatter.setLongOptPrefix("--");
        helpFormatter.setNewLine("
    -------------------
    -------------------
    ");
        helpFormatter.setLongOptSeparator("==");
        helpFormatter.setWidth(18);
    
        // 这里这里这里
        helpFormatter.printHelp("python", PatternOptionBuilder.parsePattern("vp:!f/"));
    }


    呼,希望有所帮助。

  • 相关阅读:
    LUOGU P3355 骑士共存问题(二分图最大独立集)
    LUOGU P1453 城市环路(基环树+dp)
    BZOJ 1441 Min (裴蜀定理)
    LUOGU P1342 请柬(最短路)
    LUOGU P1186 玛丽卡
    LUOGU P2580 于是他错误的点名开始了(trie树)
    l洛谷 NOIP提高组模拟赛 Day2
    bzoj 4372 烁烁的游戏——动态点分治+树状数组
    bzoj 3730 震波——动态点分治+树状数组
    hdu 5909 Tree Cutting——点分治(树形DP转为序列DP)
  • 原文地址:https://www.cnblogs.com/larryzeal/p/8362216.html
Copyright © 2020-2023  润新知