如何在Java中解析命令行参数?

lin*_*lof 547 java command-line command-line-arguments picocli

在Java中解析命令行参数的好方法是什么?

Vin*_*vic 372

最近的一颗新星是picocli(ANSI颜色,命令行自动完成,注释和编程API等等).

还要检查这些(较旧):

或滚动你自己:


例如,这是你commons-cli用来解析2个字符串参数的方法:

import org.apache.commons.cli.*;

public class Main {


    public static void main(String[] args) throws Exception {

        Options options = new Options();

        Option input = new Option("i", "input", true, "input file path");
        input.setRequired(true);
        options.addOption(input);

        Option output = new Option("o", "output", true, "output file");
        output.setRequired(true);
        options.addOption(output);

        CommandLineParser parser = new DefaultParser();
        HelpFormatter formatter = new HelpFormatter();
        CommandLine cmd;

        try {
            cmd = parser.parse(options, args);
        } catch (ParseException e) {
            System.out.println(e.getMessage());
            formatter.printHelp("utility-name", options);

            System.exit(1);
        }

        String inputFilePath = cmd.getOptionValue("input");
        String outputFilePath = cmd.getOptionValue("output");

        System.out.println(inputFilePath);
        System.out.println(outputFilePath);

    }

}
Run Code Online (Sandbox Code Playgroud)

从命令行使用:

$> java -jar target/my-utility.jar -i asd                                                                                       
Missing required option: o

usage: utility-name
 -i,--input <arg>    input file path
 -o,--output <arg>   output file
Run Code Online (Sandbox Code Playgroud)

  • 请注意,与许多其他Apache库不同,Apache CLI没有依赖项. (30认同)
  • 许多apache-commons项目的一个缺点是它们的提交越来越少,最终被淘汰. (9认同)
  • 这是Apache CLI项目的"使用场景"页面,详细说明了如何快速开始使用它:http://commons.apache.org/cli/usage.html (4认同)
  • @RemkoPopma,您的picocli库看起来很棒,真的谢谢您。但是我认为您在这里和其他帖子中所做的事情(编辑已接受的答案并在其顶部提升您的图书馆,甚至没有透露这不是该帖子的原始作者的编辑,而是您的图书馆),这是对您的审核能力的可怕滥用。将其标记为其他mod。 (3认同)
  • @AlexanderMalakhov 我想纠正一件事:[任何人](https://stackoverflow.com/help/privileges) 可以编辑(不需要审核权)并且编辑是[鼓励](https://stackoverflow.com/help/编辑)以保持帖子的相关性和最新性(当前的答案是 10 年)。也就是说,好的编辑应该平衡以避免被视为垃圾邮件,并且必须公开隶属关系。谢谢你指出这一点。 (2认同)

Ced*_*ust 302

看一下最近的JCommander.

我创造了它.我很高兴收到问题或功能要求.

  • 伟大的工具.功能强大,灵活,您不必处理烦人的传统选项解析器. (14认同)
  • @CedricBeust,这是一个很棒的图书馆,我非常感谢你.由于我们可以定义自己的Args类,然后可以传递而不依赖于库类,因此它非常灵活. (9认同)
  • 很高兴你喜欢JCommander :-)我不想为标志的处理方式添加过多的语义,所以你只需要在你使用的注释中添加同义词:@Parameter(names = {" - h"," - -help"})我认为这是一个合理的妥协. (7认同)
  • 是的,我想我会编写自己的命令行参数解析器,就像编写JCommander一样.做得好. (3认同)
  • 从水中吹出竞争! (2认同)

lex*_*ope 226

我一直在尝试维护一个Java CLI解析器列表.

  • 我注意到JOpt Simple的作者维护了一个非常相似的列表!我们需要的文本是将这些列表转换为表格,列出功能和兴趣点,因此我们的穷人可以做出明智的选择. (13认同)
  • @Ben Flynn呵呵,那里有一些非常令人惊讶和有趣的形状轮子.我想这是一种无害的方式来表明有多种方法可以做到这一点! (7认同)
  • 列出的大多数项目基本上都是放弃软件.经过列表后,我会说那些积极维护和流行的大型击球手似乎是公共场合 - cli,jcommander,args4j,jopt-simple和picocli.向诸如argparse4j和cli-parser之类的作者致歉 - 我不得不进行一些任意排名,并选择前五名,显然列表中的其他项目很受欢迎,并且仍在积极开发中. (7认同)
  • 我挑战某人包括每个解析器的最后一个稳定版本的日期。 (4认同)
  • Remko Popma的本网站。https://github.com/remkop/picocli/wiki/CLI-比较 (2认同)

Gar*_*ryF 22

我使用过JOpt,发现它非常方便:http://jopt-simple.sourceforge.net/

首页还提供了大约8个替代库的列表,检查出来并选择最适合您需求的库.


And*_*dré 21

最近有人向我指出args4j是基于注释的.我很喜欢!


Rem*_*pma 19

购买还是建造?

许多类似实用程序的小应用程序可能会使用自己的命令行解析来避免额外的外部依赖.

picocli可能很有趣.它被设计为作为源的一个更简单的替代方法,将阴影罐放入uberjar中.

您可能喜欢的另一个功能是它的彩色使用帮助.

最小的使用帮助ANSI颜色

解析器功能:

  • 基于注释:解析是一行代码
  • 强力输入所有内容 - 命令行选项以及位置参数
  • POSIX集群短期权(<command> -xvfInputFile以及<command> -x -v -f InputFile)
  • 允许最小,最大和可变数量参数的arity模型,例如"1..*","3..5"
  • 子命令(可以嵌套到任意深度)
  • 适用于Java 5及更高版本

使用帮助消息很容易使用注释进行自定义(无需编程).例如:

扩展使用帮助消息(来源)

我无法抗拒添加一个屏幕截图来显示可能的用法帮助消息.使用帮助是您的应用程序的面貌,所以要有创意,玩得开心!

picocli演示

免责声明:我创建了picocli.反馈或问题非常欢迎.

  • 纯天才!遗憾的是,这个答案被埋没在底部.Apache Commons CLI详细,有缺陷,并且很长时间没有更新.而且我不想使用Google的CLI解析器,因为我不希望根据命令行参数使用历史记录定向广告.但它看起来比picocli更冗长. (3认同)
  • 我在这里第二次@Pete...我浏览了上面的列表,这完全是浪费时间,这个埋在底部。这应该是最重要的答案。做得好!apache CLI 或大多数其他解析器无法满足我的要求。即使对于 picocli 来说,它们也具有挑战性,但它能够为我提供最接近我想要的语法/行为的东西,并且足够灵活,可以破解我真正需要的东西。额外的好处是,由于 ANSI 的支持,它看起来非常漂亮。 (3认同)

Joh*_*las 11

我知道这里的大多数人会找到 1000 万个不喜欢我的方式的理由,但没关系。我喜欢保持简单,所以我只是使用 '=' 将键与值分开,并将它们存储在 HashMap 中,如下所示:

Map<String, String> argsMap = new HashMap<>();
for (String arg: args) {
    String[] parts = arg.split("=");
    argsMap.put(parts[0], parts[1]);
} 
Run Code Online (Sandbox Code Playgroud)

您可以始终维护一个包含您期望的参数的列表,以帮助用户以防他忘记参数或使用错误的参数......但是,如果您想要太多功能,这个解决方案无论如何都不适合您。


Pau*_*aul 9

这是Google的命令行解析库,作为Bazel项目的一部分开源.我个人认为它是最好的,比Apache CLI容易得多.

https://github.com/pcj/google-options

安装

巴泽尔

maven_jar(
    name = "com_github_pcj_google_options",
    artifact = "com.github.pcj:google-options:jar:1.0.0",
    sha1 = "85d54fe6771e5ff0d54827b0a3315c3e12fdd0c7",
)
Run Code Online (Sandbox Code Playgroud)

摇篮

dependencies {
  compile 'com.github.pcj:google-options:1.0.0'
}
Run Code Online (Sandbox Code Playgroud)

Maven的

<dependency>
  <groupId>com.github.pcj</groupId>
  <artifactId>google-options</artifactId>
  <version>1.0.0</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

用法

创建一个扩展OptionsBase和定义您的类的类@Option.

package example;

import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionsBase;

import java.util.List;

/**
 * Command-line options definition for example server.
 */
public class ServerOptions extends OptionsBase {

  @Option(
      name = "help",
      abbrev = 'h',
      help = "Prints usage info.",
      defaultValue = "true"
    )
  public boolean help;

  @Option(
      name = "host",
      abbrev = 'o',
      help = "The server host.",
      category = "startup",
      defaultValue = ""
  )
  public String host;

  @Option(
    name = "port",
    abbrev = 'p',
    help = "The server port.",
    category = "startup",
    defaultValue = "8080"
    )
    public int port;

  @Option(
    name = "dir",
    abbrev = 'd',
    help = "Name of directory to serve static files.",
    category = "startup",
    allowMultiple = true,
    defaultValue = ""
    )
    public List<String> dirs;

}
Run Code Online (Sandbox Code Playgroud)

解析参数并使用它们.

package example;

import com.google.devtools.common.options.OptionsParser;
import java.util.Collections;

public class Server {

  public static void main(String[] args) {
    OptionsParser parser = OptionsParser.newOptionsParser(ServerOptions.class);
    parser.parseAndExitUponError(args);
    ServerOptions options = parser.getOptions(ServerOptions.class);
    if (options.host.isEmpty() || options.port < 0 || options.dirs.isEmpty()) {
      printUsage(parser);
      return;
    }

    System.out.format("Starting server at %s:%d...\n", options.host, options.port);
    for (String dirname : options.dirs) {
      System.out.format("\\--> Serving static files at <%s>\n", dirname);
    }
  }

  private static void printUsage(OptionsParser parser) {
    System.out.println("Usage: java -jar server.jar OPTIONS");
    System.out.println(parser.describeOptions(Collections.<String, String>emptyMap(),
                                              OptionsParser.HelpVerbosity.LONG));
  }

}
Run Code Online (Sandbox Code Playgroud)

https://github.com/pcj/google-options


Mar*_*ski 8

看看Commons CLI项目,那里有很多好东西.


Osc*_*Ryz 8

叶氏.

我想你正在寻找这样的东西:http: //commons.apache.org/cli

Apache Commons CLI库提供用于处理命令行界面的API.


mep*_*ell 7

也许这些

  • picocli"一个强大的微型命令行界面".Picocli是Java的命令行参数解析器库 - 具有ANSI着色的使用帮助和命令行完成.嵌套的子命令,详细的用户手册以及作为源代码的能力,以避免依赖于picocli的jar也是值得注意的.
  • 用于Java的JArgs命令行选项解析套件 - 这个小项目提供了一个方便,紧凑,预打包和全面记录的命令行选项解析器套件,供Java程序员使用.最初,提供了与GNU风格的'getopt'兼容的解析.

  • ritopt,Java的终极选项解析器 - 虽然已经提出了几个命令行选项标准,但ritopt遵循opt包中规定的约定.


Ste*_*erl 7

如果您已经在使用 Spring Boot,则参数解析是开箱即用的。

如果你想在启动后运行一些东西,实现ApplicationRunner接口:

@SpringBootApplication
public class Application implements ApplicationRunner {

  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }

  @Override
  public void run(ApplicationArguments args) {
    args.containsOption("my-flag-option"); // test if --my-flag-option was set
    args.getOptionValues("my-option");     // returns values of --my-option=value1 --my-option=value2 
    args.getOptionNames();                 // returns a list of all available options
    // do something with your args
  }
}
Run Code Online (Sandbox Code Playgroud)

您的run方法将在上下文成功启动后被调用。

如果您需要启动应用程序上下文之前访问参数,您只需手动解析应用程序参数:

@SpringBootApplication
public class Application implements ApplicationRunner {

  public static void main(String[] args) {
    ApplicationArguments arguments = new DefaultApplicationArguments(args);
    // do whatever you like with your arguments
    // see above ...
    SpringApplication.run(Application.class, args);
  }

}
Run Code Online (Sandbox Code Playgroud)

最后,如果您需要访问 bean 中的参数,只需注入ApplicationArguments

@Component
public class MyBean {

   @Autowired
   private ApplicationArguments arguments;

   // ...
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*ler 6

你可能会发现这篇不幸的元文章作为一个有趣的起点:

http://furiouspurpose.blogspot.com/2008/07/command-line-parsing-libraries-for-java.html

  • 那家伙很无用"Commons CLI显然是这里最古老的选择,并没有得到评论者的很多尊重,所以我并没有真正关注这个......",但是还是要感谢这个链接. (2认同)

小智 5

我又写了一篇:http://argparse4j.sourceforge.net/

Argparse4j是Java的命令行参数解析器库,基于Python的argparse.