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

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

459785 次浏览

看看这些:

或者自己卷:


这是你如何使用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 = 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

看看下议院CLI项目,里面有很多好东西。

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

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

对啊。

我想你在寻找这样的东西: # EYZ0 < / p >

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

最近有人给我指了args4j,它是基于注释的。我真的很喜欢!

看看最近的JCommander

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

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

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

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

这是谷歌的命令行解析库,作为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",
)

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的类。

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等中使用。

Minimal usage help with ANSI colors

特点:

  • 注释基于:声明避免重复表达程序员意图
  • 方便:解析用户输入并使用一行代码运行业务逻辑
  • 强类型一切-命令行选项以及位置参数
  • POSIX聚集的短选项(<command> -xvfInputFile<command> -x -v -f InputFile)
  • 细粒度控制:一个允许最小、最大和可变数量参数的arity模型,例如"1..*""3..5"
  • 子命令(可以嵌套到任意深度)
  • 功能丰富的:可组合的参数组,分隔引用的参数,可重复的子命令,等等
  • 用户友好的:使用帮助消息使用颜色来对比重要元素,如使用帮助的其余部分的选项名称和用户上的减少认知负荷
  • 将你的应用作为GraalVM本机映像 .分发
  • 工作与Java 5和更高
  • 广泛细致< >强文档< / >强

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

# EYZ0 (# EYZ1)

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

picocli demo

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

如果你想要一些轻量级的(罐子大小~ 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);
}

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

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

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

优点:

    需要学习的类非常少,只需要查看存储库中的README上的两个小示例,您已经学习了90%;在没有任何其他知识的情况下开始编写CLI/Parser; ReadyCLI允许以最自然的方式编码cli
  • 它是根据开发人员的经验设计的;它主要使用Builder设计模式和Lambda表达式的功能接口,以允许非常快速的编码;
  • 它支持选项旗帜Sub-Commands;
  • 它允许从命令行解析参数,并构建更复杂和交互式的cli;
  • CLI可以在标准I/O上启动,就像在任何其他I/O接口上一样容易,比如套接字;
  • 它为命令文档提供了很好的支持。

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

看看春天的壳

Spring Shell的功能包括

  • 一个简单的、注释驱动的编程模型,用于提供定制命令
  • 使用Spring Boot自动配置功能作为命令插件策略的基础
  • 制表符完成、着色和脚本执行
  • 自定义命令提示符、shell历史文件名、结果和错误的处理
  • 基于域特定条件的命令动态启用
  • 与bean验证API集成
  • 已经内置的命令,如清除屏幕,华丽的帮助,退出
  • ASCII艺术表,格式,对齐,花式边框等。