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


当前回答

现在是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。欢迎反馈或提问。

其他回答

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

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

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

现在是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。欢迎反馈或提问。

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

   // ...
}

看看这些:

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