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


看看这些:

http://commons.apache.org/cli/ http://www.martiansoftware.com/jsap/

或者自己卷:

http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html


例如,这是你如何使用common -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 = null;//not a good practice, it serves it purpose 

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

    }

}

命令行用法:

$> 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

看看Commons CLI项目,里面有很多好东西。


也许这些

JArgs命令行选项解析 这个小项目为Java程序员提供了一个方便、紧凑、预打包和全面文档化的命令行选项解析器套件。最初,提供了与gnu风格的“getopt”兼容的解析。 ritopt, Java的终极选项解析器——尽管已经预先提出了几个命令行选项标准,ritopt仍然遵循opt包中规定的约定。


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

首页还提供了一个大约8个备选库的列表,检查它们并选择最适合您的需求。


是的。

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

Apache Commons CLI库提供了一个用于处理命令行接口的API。


如果你熟悉gnu getopt,有一个Java端口:http://www.urbanophile.com/arenn/hacking/download.htm。

似乎有一些类是这样做的:

http://docs.sun.com/source/816-5618-10/netscape/ldap/util/GetOpt.html http://xml.apache.org/xalan-j/apidocs/org/apache/xalan/xsltc/cmdline/getopt/GetOpt.html


最近有人向我推荐了基于注释的args4j。我真的很喜欢!


看一看最近的JCommander。

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


我一直试图维护一个Java CLI解析器列表。

航空公司 Active Fork: https://github.com/rvesse/airline argparse4j argparse args4j clajr cli-parser CmdLn 命令行 DocOpt.java 海豚getopt DPML CLI (Jakarta Commons CLI2分支) 马蒂亚斯·劳克斯博士 Jakarta Commons CLI jargo jargp jargs java-getopt jbock JCLAP jcmdline jcommander jcommando Jewelcli(作者:我) JOpt简单 jsap naturalcli Object Mentor CLI文章(关于重构和TDD的更多内容) parse-cmd ritopt 罗普 TE-Code命令 picocli有ANSI彩色使用帮助和自动完成


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

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


航空公司@ Github看起来不错。它基于注释,并试图模拟Git命令行结构。


这是谷歌的命令行解析库,作为Bazel项目的一部分是开源的。我个人认为它是最好的,比Apache CLI简单得多。

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

安装

Bazel

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

Gradle

dependencies {
  compile 'com.github.pcj:google-options:1.0.0'
}

Maven

<dependency>
  <groupId>com.github.pcj</groupId>
  <artifactId>google-options</artifactId>
  <version>1.0.0</version>
</dependency>

使用

创建一个扩展OptionsBase并定义@Option(s)的类。

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;

}

解析参数并使用它们。

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

}

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


现在是2022年,是时候比Commons CLI做得更好了……: -)

您应该构建自己的Java命令行解析器,还是使用库?

许多类似于实用程序的小型应用程序可能会滚动自己的命令行解析,以避免额外的外部依赖。Picocli可能是一个有趣的替代方案。

Picocli是一个现代化的库和框架,用于轻松构建强大的、用户友好的、支持graalvm的命令行应用程序。它存在于一个源文件中,所以应用程序可以将它作为源文件来包含,以避免添加依赖项。

它支持颜色、自动补全、子命令等等。用Java编写,可从Groovy、Kotlin、Scala等中使用。

特点:

Annotation based: declarative, avoids duplication and expresses programmer intent Convenient: parse user input and run your business logic with one line of code Strongly typed everything - command line options as well as positional parameters POSIX clustered short options (<command> -xvfInputFile as well as <command> -x -v -f InputFile) Fine-grained control: an arity model that allows a minimum, maximum and variable number of parameters, e.g, "1..*", "3..5" Subcommands (can be nested to arbitrary depth) Feature-rich: composable arg groups, splitting quoted args, repeatable subcommands, and many more User-friendly: usage help message uses colors to contrast important elements like option names from the rest of the usage help to reduce the cognitive load on the user Distribute your app as a GraalVM native image Works with Java 5 and higher Extensive and meticulous documentation

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

(源)

我忍不住又加了一张截图来展示使用帮助信息的可能性。使用帮助是应用程序的门面,所以要有创意,玩得开心!

声明:我创建了picocli。欢迎反馈或提问。


如果您想要一些轻量级的(jar大小~ 20 kb)并且使用简单的东西,您可以尝试参数解析器。它可以在大多数用例中使用,支持在参数中指定数组,并且不依赖于任何其他库。它适用于Java 1.5或更高版本。下面摘录了一个如何使用它的例子:

public static void main(String[] args) {
    String usage = "--day|-d day --mon|-m month [--year|-y year][--dir|-ds directoriesToSearch]";
    ArgumentParser argParser = new ArgumentParser(usage, InputData.class);
    InputData inputData = (InputData) argParser.parse(args);
    showData(inputData);

    new StatsGenerator().generateStats(inputData);
}

更多的例子可以在这里找到


Argparse4j是我发现的最好的。它模仿Python的argparse库,非常方便和强大。


我知道这里的大多数人会找到一千万个理由来解释他们为什么不喜欢我的方式,但没关系。我喜欢让事情变得简单,所以我只是使用'='将键和值分开,并将它们存储在一个HashMap中,就像这样:

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

您可以始终维护一个包含您所期望的参数的列表,以帮助用户避免忘记参数或使用错误的参数……然而,如果你想要太多的功能,这个解决方案并不适合你。


正如前面提到的一个评论(https://github.com/pcj/google-options)是一个很好的开始。

我想补充的一点是:

1)如果您遇到一些解析器反射错误,请尝试使用更新版本的guava。在我的例子中:

maven_jar(
    name = "com_google_guava_guava",
    artifact = "com.google.guava:guava:19.0",
    server = "maven2_server",
)

maven_jar(
    name = "com_github_pcj_google_options",
    artifact = "com.github.pcj:google-options:jar:1.0.0",
    server = "maven2_server",
)

maven_server(
    name = "maven2_server",
    url = "http://central.maven.org/maven2/",
)

2)当运行命令行时:

bazel run path/to/your:project -- --var1 something --var2 something -v something

3)当你需要使用帮助时,只需输入:

bazel run path/to/your:project -- --help

For Spring users, we should mention also https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/env/SimpleCommandLinePropertySource.html and his twin brother https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/env/JOptCommandLinePropertySource.html (JOpt implementation of the same functionality). The advantage in Spring is that you can directly bind the command line arguments to attributes, there is an example here https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/env/CommandLinePropertySource.html


如果您已经在使用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方法将在上下文成功启动后被调用。

如果你需要在启动你的应用程序上下文之前访问参数,你可以简单地手动解析应用程序参数:

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

}

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

@Component
public class MyBean {

   @Autowired
   private ApplicationArguments arguments;

   // ...
}

我想向您展示我的实现:ReadyCLI

优点:

for lazy programmers: a very small number of classes to learn, just see the two small examples on the README in the repository and you are already at 90% of learning; just start coding your CLI/Parser without any other knowledge; ReadyCLI allows coding CLIs in the most natural way; it is designed with Developer Experience in mind; it largely uses the Builder design pattern and functional interfaces for Lambda Expressions, to allow a very quick coding; it supports Options, Flags and Sub-Commands; it allows to parse arguments from command-line and to build more complex and interactive CLIs; a CLI can be started on Standard I/O just as easily as on any other I/O interface, such as sockets; it gives great support for documentation of commands.

我开发这个项目是因为我需要新的功能(选项,标志,子命令),并且可以在我的项目中以最简单的方式使用。


看看Spring Shell

Spring Shell’s features include A simple, annotation driven, programming model to contribute custom commands Use of Spring Boot auto-configuration functionality as the basis for a command plugin strategy Tab completion, colorization, and script execution Customization of command prompt, shell history file name, handling of results and errors Dynamic enablement of commands based on domain specific criteria Integration with the bean validation API Already built-in commands, such as clear screen, gorgeous help, exit ASCII art Tables, with formatting, alignment, fancy borders, etc.