在Java中解析命令行参数的好方法是什么?
How to parse java command line arguments?
。但是没有人真正想编写代码来执行此操作,而是使用一种工具。但是,寻找工具之类的工具并不是建设性的:(
在Java中解析命令行参数的好方法是什么?
How to parse java command line arguments?
。但是没有人真正想编写代码来执行此操作,而是使用一种工具。但是,寻找工具之类的工具并不是建设性的:(
Answers:
检查这些:
或自己动手:
例如,这是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
看一下最近的JCommander。
我创造了它。我很高兴收到问题或功能要求。
我一直在尝试维护Java CLI解析器的列表。
现在是2020年,是时候比Commons CLI做得更好了... :-)
您应该构建自己的Java命令行解析器还是使用库?
许多类似小型实用程序的应用程序可能会滚动自己的命令行解析,以避免额外的外部依赖性。picocli可能是一个有趣的选择。
Picocli是一个现代的库和框架,可轻松构建功能强大,用户友好且启用GraalVM的命令行应用程序。它位于1个源文件中,因此应用程序可以将其包含为源文件以避免添加依赖项。
它支持颜色,自动补全,子命令等。用Java编写,可用于Groovy,Kotlin,Scala等。
特征:
<command> -xvfInputFile
以及<command> -x -v -f InputFile
)"1..*"
,"3..5"
使用帮助消息很容易通过注释进行自定义(无需编程)。例如:
(来源)
我忍不住要再添加一个屏幕截图,以显示可能的使用帮助消息。使用帮助是您应用程序的面目,因此请发挥创造力并尽情玩乐!
免责声明:我创建了picocli。反馈或问题非常欢迎。
这是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'
}
<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));
}
}
myexecutable -c file.json -d 42 --outdir ./out
。而且我看不到您如何定义短/多/描述选项...干杯
看一下Commons CLI项目,那里有很多不错的东西。
我知道这里的大多数人都会找到1000万个理由,他们为什么不喜欢我的方式,但没关系。我喜欢使事情保持简单,因此我只是使用'='将键与值分开,并将其存储在HashMap中,如下所示:
Map<String, String> argsMap = new HashMap<>();
for (String arg: args) {
String[] parts = arg.split("=");
argsMap.put(parts[0], parts[1]);
}
您总是可以维护一个包含期望参数的列表,以帮助用户忘记参数或使用了错误的参数。但是,如果您想要太多的功能,那么该解决方案就不适合您。
也许这些
用于Java的JArgs命令行选项解析套件 -这个小项目为Java程序员提供了一个方便,紧凑,预先打包且文档全面的命令行选项解析器套件。最初,提供了与GNU风格的“ getopt”兼容的解析。
ritopt,Java的Ultimate Options Parser-尽管已经提出了几种命令行选项标准,但ritopt遵循opt软件包中规定的约定。
您可能会发现这不愉快的元文章很有趣,可以作为起点:
http://furiouspurpose.blogspot.com/2008/07/command-line-parsing-libraries-for-java.html
我写了另一个:http : //argparse4j.sourceforge.net/
Argparse4j是基于Python的argparse的Java命令行参数解析器库。
@ Github的航空公司看起来不错。它基于注释,正在尝试模拟Git命令行结构。
如果您已经在使用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;
// ...
}
我发现Argparse4j是最好的。它模仿Python的argparse库,该库非常方便且强大。
如果您想要轻量级的东西(罐子大小〜20 kb)并且易于使用,则可以尝试arguments-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);
}
可以在这里找到更多示例
正如前面提到的评论之一(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
对于Spring用户,我们还应该提到https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/env/SimpleCommandLinePropertySource.html 和他的双胞胎兄弟https://docs.spring .io / spring / docs / current / javadoc-api / org / springframework / core / env / JOptCommandLinePropertySource.html(具有相同功能的JOpt实现)。Spring的优势在于您可以直接将命令行参数绑定到属性,这里有一个示例https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/env/ CommandLinePropertySource.html