如果我想解析这个怎么办?
java MyProgram -r opt1 -S opt2 arg1 arg2 arg3 arg4 --test -A opt3
我想在程序中得到的结果是:
regular Java args[] of size=4
org.apache.commons.cli.Options[] of size=3
org.apache.commons.cli.Options[] #2 of size=1
我更愿意使用Apache Commons CLI,但文档对我上面提到的案例有点不清楚。具体来说,文档没有告诉您如何处理我在下面指定的第三种类型的选项:
1. options with a "-" char 2. options with a "--" char 3. options without any marker, or "bare args"
我希望Apache Commons CLI能够正常运行,但是如果这些args没有选项前缀,STILL能够将常规args传递给程序。也许它确实如此,但是当我通读它时,文档并没有这么说......
答案 0 :(得分:59)
使用Apache Commons CLI library commandline.getArgs()获取arg1,arg2,arg3和arg4。这是一些代码:
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.Option.Builder;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.ParseException;
public static void main(String[] parameters)
{
CommandLine commandLine;
Option option_A = Option.builder("A")
.required(true)
.desc("The A option")
.longOpt("opt3")
.build();
Option option_r = Option.builder("r")
.required(true)
.desc("The r option")
.longOpt("opt1")
.build();
Option option_S = Option.builder("S")
.required(true)
.desc("The S option")
.longOpt("opt2")
.build();
Option option_test = Option.builder()
.required(true)
.desc("The test option")
.longOpt("test")
.build();
Options options = new Options();
CommandLineParser parser = new DefaultParser();
String[] testArgs =
{ "-r", "opt1", "-S", "opt2", "arg1", "arg2",
"arg3", "arg4", "--test", "-A", "opt3", };
options.addOption(option_A);
options.addOption(option_r);
options.addOption(option_S);
options.addOption(option_test);
try
{
commandLine = parser.parse(options, testArgs);
if (commandLine.hasOption("A"))
{
System.out.print("Option A is present. The value is: ");
System.out.println(commandLine.getOptionValue("A"));
}
if (commandLine.hasOption("r"))
{
System.out.print("Option r is present. The value is: ");
System.out.println(commandLine.getOptionValue("r"));
}
if (commandLine.hasOption("S"))
{
System.out.print("Option S is present. The value is: ");
System.out.println(commandLine.getOptionValue("S"));
}
if (commandLine.hasOption("test"))
{
System.out.println("Option test is present. This is a flag option.");
}
{
String[] remainder = commandLine.getArgs();
System.out.print("Remaining arguments: ");
for (String argument : remainder)
{
System.out.print(argument);
System.out.print(" ");
}
System.out.println();
}
}
catch (ParseException exception)
{
System.out.print("Parse error: ");
System.out.println(exception.getMessage());
}
}
答案 1 :(得分:30)
你可以手动完成。
NB:可能更适合使用HashMap而不是opts的内部类。
/** convenient "-flag opt" combination */
private class Option {
String flag, opt;
public Option(String flag, String opt) { this.flag = flag; this.opt = opt; }
}
static public void main(String[] args) {
List<String> argsList = new ArrayList<String>();
List<Option> optsList = new ArrayList<Option>();
List<String> doubleOptsList = new ArrayList<String>();
for (int i = 0; i < args.length; i++) {
switch (args[i].charAt(0)) {
case '-':
if (args[i].length < 2)
throw new IllegalArgumentException("Not a valid argument: "+args[i]);
if (args[i].charAt(1) == '-') {
if (args[i].length < 3)
throw new IllegalArgumentException("Not a valid argument: "+args[i]);
// --opt
doubleOptsList.add(args[i].substring(2, args[i].length));
} else {
if (args.length-1 == i)
throw new IllegalArgumentException("Expected arg after: "+args[i]);
// -opt
optsList.add(new Option(args[i], args[i+1]));
i++;
}
break;
default:
// arg
argsList.add(args[i]);
break;
}
}
// etc
}
答案 2 :(得分:12)
我喜欢这个。很简单,每个参数都有多个参数:
final Map<String, List<String>> params = new HashMap<>();
List<String> options = null;
for (int i = 0; i < args.length; i++) {
final String a = args[i];
if (a.charAt(0) == '-') {
if (a.length() < 2) {
System.err.println("Error at argument " + a);
return;
}
options = new ArrayList<>();
params.put(a.substring(1), options);
}
else if (options != null) {
options.add(a);
}
else {
System.err.println("Illegal parameter usage");
return;
}
}
例如:
-arg1 1 2 --arg2 3 4
System.out.print(params.get("arg1").get(0)); // 1
System.out.print(params.get("arg1").get(1)); // 2
System.out.print(params.get("-arg2").get(0)); // 3
System.out.print(params.get("-arg2").get(1)); // 4
答案 3 :(得分:4)
我意识到这个问题提到了Commons CLI的首选项,但是我想当问这个问题时,就Java命令行解析库而言,没有太多选择。但是九年后的2020年,您是否宁愿编写如下代码?
import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
import picocli.CommandLine.Parameters;
import java.io.File;
import java.util.List;
import java.util.concurrent.Callable;
@Command(name = "myprogram", mixinStandardHelpOptions = true,
description = "Does something useful.", version = "1.0")
public class MyProgram implements Callable<Integer> {
@Option(names = "-r", description = "The r option") String rValue;
@Option(names = "-S", description = "The S option") String sValue;
@Option(names = "-A", description = "The A file") File aFile;
@Option(names = "--test", description = "The test option") boolean test;
@Parameters(description = "Positional params") List<String> positional;
@Override
public Integer call() {
System.out.printf("-r=%s%n", rValue);
System.out.printf("-S=%s%n", sValue);
System.out.printf("-A=%s%n", aFile);
System.out.printf("--test=%s%n", test);
System.out.printf("positionals=%s%n", positional);
return 0;
}
public static void main(String... args) {
System.exit(new CommandLine(new MyProgram()).execute(args));
}
}
通过运行问题中的命令来执行:
java MyProgram -r opt1 -S opt2 arg1 arg2 arg3 arg4 --test -A opt3
我喜欢这段代码的地方是:
call
方法中的业务逻辑没有与解析相关的逻辑--help
和--version
选项提供自动使用和版本帮助上述功能只是使用picocli(https://picocli.info)库时获得的部分功能。
现在,请记住,我是picocli的作者,完全,完全和完全有偏见。 :-) 但我确实相信,到2020年,与Commons CLI相比,我们拥有构建命令行应用程序的更好选择。
答案 4 :(得分:3)
这是@DwB解决方案升级到Commons CLI 1.3.1合规性(替换弃用的组件OptionBuilder和GnuParser)。 Apache文档使用的实例在现实生活中有未标记/裸参数但忽略它们。感谢@DwB展示它的工作原理。
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
public static void main(String[] parameters) {
CommandLine commandLine;
Option option_A = Option.builder("A").argName("opt3").hasArg().desc("The A option").build();
Option option_r = Option.builder("r").argName("opt1").hasArg().desc("The r option").build();
Option option_S = Option.builder("S").argName("opt2").hasArg().desc("The S option").build();
Option option_test = Option.builder().longOpt("test").desc("The test option").build();
Options options = new Options();
CommandLineParser parser = new DefaultParser();
options.addOption(option_A);
options.addOption(option_r);
options.addOption(option_S);
options.addOption(option_test);
String header = " [<arg1> [<arg2> [<arg3> ...\n Options, flags and arguments may be in any order";
String footer = "This is DwB's solution brought to Commons CLI 1.3.1 compliance (deprecated methods replaced)";
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp("CLIsample", header, options, footer, true);
String[] testArgs =
{ "-r", "opt1", "-S", "opt2", "arg1", "arg2",
"arg3", "arg4", "--test", "-A", "opt3", };
try
{
commandLine = parser.parse(options, testArgs);
if (commandLine.hasOption("A"))
{
System.out.print("Option A is present. The value is: ");
System.out.println(commandLine.getOptionValue("A"));
}
if (commandLine.hasOption("r"))
{
System.out.print("Option r is present. The value is: ");
System.out.println(commandLine.getOptionValue("r"));
}
if (commandLine.hasOption("S"))
{
System.out.print("Option S is present. The value is: ");
System.out.println(commandLine.getOptionValue("S"));
}
if (commandLine.hasOption("test"))
{
System.out.println("Option test is present. This is a flag option.");
}
{
String[] remainder = commandLine.getArgs();
System.out.print("Remaining arguments: ");
for (String argument : remainder)
{
System.out.print(argument);
System.out.print(" ");
}
System.out.println();
}
}
catch (ParseException exception)
{
System.out.print("Parse error: ");
System.out.println(exception.getMessage());
}
}
输出:
usage: CLIsample [-A <opt3>] [-r <opt1>] [-S <opt2>] [--test]
[<arg1> [<arg2> [<arg3> ...
Options, flags and arguments may be in any order
-A <opt3> The A option
-r <opt1> The r option
-S <opt2> The S option
--test The test option
This is DwB's solution brought to Commons CLI 1.3.1 compliance (deprecated
methods replaced)
Option A is present. The value is: opt3
Option r is present. The value is: opt1
Option S is present. The value is: opt2
Option test is present. This is a flag option.
Remaining arguments: arg1 arg2 arg3 arg4
答案 5 :(得分:2)
你可以使用https://github.com/jankroken/commandline,以下是如何做到这一点:
为了使这个例子有效,我必须对参数的含义做出假设 - 只需在这里选择一些东西......
-r opt1 => replyAddress=opt1
-S opt2 arg1 arg2 arg3 arg4 => subjects=[opt2,arg1,arg2,arg3,arg4]
--test = test=true (default false)
-A opt3 => address=opt3
然后可以这样设置:
public class MyProgramOptions {
private String replyAddress;
private String address;
private List<String> subjects;
private boolean test = false;
@ShortSwitch("r")
@LongSwitch("replyAddress") // if you also want a long variant. This can be skipped
@SingleArgument
public void setReplyAddress(String replyAddress) {
this.replyAddress = replyAddress;
}
@ShortSwitch("S")
@AllAvailableArguments
public void setSubjects(List<String> subjects) {
this.subjects = subjects;
}
@LongSwitch("test")
@Toggle(true)
public void setTest(boolean test) {
this.test = test;
}
@ShortSwitch("A")
@SingleArgument
public void setAddress(String address) {
this.address = address;
}
// getters...
}
然后在main方法中,您可以这样做:
public final static void main(String[] args) {
try {
MyProgramOptions options = CommandLineParser.parse(MyProgramOptions.class, args, OptionStyle.SIMPLE);
// and then you can pass options to your application logic...
} catch
...
}
}
答案 6 :(得分:1)
您可以在REFCODES.ORG上的refcodes-console使用refcodes-console
工件:
Option<String> r = new StringOptionImpl( "-r", null, "opt1", "..." );
Option<String> s = new StringOptionImpl( "-S", null, "opt2", "..." );
Operand<String> arg1 = new StringOperandImpl( "arg1", "..." );
Operand<String> arg2 = new StringOperandImpl( "arg2", "..." );
Operand<String> arg3 = new StringOperandImpl( "arg3", "..." );
Operand<String> arg4 = new StringOperandImpl( "arg4", "..." );
Switch test = new SwitchImpl( null, "--test", "..." );
Option<String> a = new StringOptionImpl( "-A", null, "opt3", "..." );
Condition theRoot = new AndConditionImpl( r, s, a, arg1, arg2, arg3, arg4,
test );
使用根条件创建参数解析器ArgsParserImpl
:
ArgsParser theArgsParser = new ArgsParserImpl( theRoot );
theArgsParser.setName( "MyProgramm" );
theArgsParser.setSyntaxNotation( SyntaxNotation.GNU_POSIX );
在上面定义语法,在下面调用解析器:
theArgsParser.printUsage();
theArgsParser.printSeparatorLn();
theArgsParser.printOptions();
theArgsParser.evalArgs( new String[] {
"-r", "RRRRR", "-S", "SSSSS", "11111", "22222", "33333", "44444",
"--test", "-A", "AAAAA"
} );
如果您提供了一些不错的说明,theArgsParser.printUsage()
甚至会向您展示精美的打印用法:
Usage: MyProgramm -r <opt1> -S <opt2> -A <opt3> arg1 arg2 arg3 arg4 --test
在上面的示例所有定义的参数必须由用户传递,否则解析器将检测错误的用法。如果
--test
切换为可选(或任何其他参数),请按以下方式分配theRoot
:
theRoot = new AndConditionImpl(r,s,a,arg1,arg2,arg3,arg4, new OptionalImpl(test));
然后你的语法如下:
Usage: MyProgramm -r <opt1> -S <opt2> -A <opt3> arg1 arg2 arg3 arg4 [--test]
您在StackOverFlowExamle中找到的案例的完整示例。你可以使用AND,OR,XOR条件和任何类型的嵌套......希望这会有所帮助。
按如下方式评估已解析的参数:
r.getValue() );
或if (test.getValue() == true) ...
:
LOGGER.info( "r :=" + r.getValue() );
LOGGER.info( "S :=" + s.getValue() );
LOGGER.info( "arg1 :=" + arg1.getValue() );
LOGGER.info( "arg2 :=" + arg2.getValue() );
LOGGER.info( "arg3 :=" + arg3.getValue() );
LOGGER.info( "arg4 :=" + arg4.getValue() );
LOGGER.info( "test :=" + test.getValue() + "" );
LOGGER.info( "A :=" + a.getValue() );
答案 7 :(得分:0)
好的,感谢Charles Goodwin的概念。这是答案:
import java.util.*;
public class Test {
public static void main(String[] args) {
List<String> argsList = new ArrayList<String>();
List<String> optsList = new ArrayList<String>();
List<String> doubleOptsList = new ArrayList<String>();
for (int i=0; i < args.length; i++) {
switch (args[i].charAt(0)) {
case '-':
if (args[i].charAt(1) == '-') {
int len = 0;
String argstring = args[i].toString();
len = argstring.length();
System.out.println("Found double dash with command " +
argstring.substring(2, len) );
doubleOptsList.add(argstring.substring(2, len));
} else {
System.out.println("Found dash with command " +
args[i].charAt(1) + " and value " + args[i+1] );
i= i+1;
optsList.add(args[i]);
}
break;
default:
System.out.println("Add a default arg." );
argsList.add(args[i]);
break;
}
}
}
}
答案 8 :(得分:0)
java中命令行的简单代码:
class CMDLineArgument
{
public static void main(String args[])
{
String name=args[0];
System.out.println(name);
}
}