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

时间:2008-12-15 07:46:11

标签: java command-line command-line-arguments picocli

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

22 个答案:

答案 0 :(得分:343)

检查这些:

或推出自己的:


例如,这是您使用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);

    }

}

从命令行使用:

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

答案 1 :(得分:294)

答案 2 :(得分:220)

答案 3 :(得分:22)

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

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

答案 4 :(得分:20)

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

答案 5 :(得分:11)

购买还是建造?

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

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

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

Minimal usage help with ANSI colors

解析器功能:

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

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

Extended usage help messagesource

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

picocli demo

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

答案 6 :(得分: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",
)

摇篮

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

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

答案 7 :(得分:8)

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

答案 8 :(得分:8)

叶氏。

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

  

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

答案 9 :(得分:7)

也许这些

答案 10 :(得分:6)

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

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

答案 11 :(得分:5)

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

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

答案 12 :(得分:5)

答案 13 :(得分:4)

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

答案 14 :(得分:3)

我知道这里的大多数人会发现一千万个为什么他们不喜欢我的方式但没关系的原因。我喜欢使事情保持简单,因此我只是使用'='将键与值分开,并将其存储在HashMap中,如下所示:

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

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

答案 15 :(得分:2)

我不建议使用Apache Common CLI库,因为它是非线程安全的。 它使用具有静态变量和方法的有状态类来执行内部工作(例如OptionBuilder),并且只应在单线程强控制情况下使用。

答案 16 :(得分:2)

如果你想要轻量级(罐子大小~20 kb)并且使用简单,你可以试试argument-parser。它可以在大多数用例中使用,支持在参数中指定数组,并且不依赖于任何其他库。它适用于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);
}

可以找到更多示例here

答案 17 :(得分:1)

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

答案 18 :(得分:1)

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

优点:

  • 对于懒惰的程序员:要学习的类非常少,只需查看存储库中 README 中的两个小示例,您就已经学习了 90%;无需任何其他知识即可开始编写 CLI/Parser 代码; ReadyCLI 允许以最自然的方式编写 CLI;
  • 它的设计考虑到了开发者体验;它主要使用 Builder 设计模式和 Lambda 表达式的功能接口,以实现非常快速的编码;
  • 它支持选项标志子命令
  • 它允许从命令行解析参数并构建更复杂和交互式的 CLI;
  • CLI 可以像在任何其他 I/O 接口(例如套接字)上一样轻松地在标准 I/O 上启动;
  • 它为命令文档提供了极大的支持。

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

答案 19 :(得分:0)

就像前面提到的评论之一(https://github.com/pcj/google-options)一样,是一个不错的选择。

我想添加的一件事是:

1)如果遇到解析器反射错误,请尝试使用更新版本的番石榴。就我而言:

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

答案 20 :(得分:0)

如果您已经在使用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;

   // ...
}

答案 21 :(得分:-1)