2011-09-07 132 views
33

如果我想解析此:解析参数Java命令行程序

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的百科全书CLI的工作,但仍然能够通过定期的参数传递给了程序如果这些参数没有选项前缀。也许它的确如此,但是当我通读它时文档没有这么说...

+1

的可能的复制(http://stackoverflow.com/questions/367706/how-to-parse-command- line-arguments-in-java) – xenteros

回答

19

您可以手动完成。

注意:可能会更好地使用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 
} 
+1

你应该检查args [i]的长度! –

+0

我只是在打字!如果你想要看起来,你也可以使用散列表而不是switch语句。 – IslandCow

+0

@Jon Bright更好吗? –

0

好的,谢谢查尔斯古德温的概念。下面是答案:

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;   
     }  
    } 
    } 

} 
+1

它仍然不是很正确,因为你没有存储'-flag opt'组合。 –

+0

我把它写成了一个Beanshell解决方案:http:// stackoverflow。com/questions/7356979/java-beanshell -scripting-with-args-to-the-the-program – djangofan

44

使用Apache Commons CLI library commandline.getArgs()来获取ARG1,ARG2,ARG3和ARG4。下面是一些代码:Java中的命令行



    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()); 
     } 
    } 

+0

这个答案中的一些方法不再被支持。当前CLI版本的示例:https://commons.apache.org/proper/commons-cli/usage.html – stuart

0

简单代码:

class CMDLineArgument 
{ 
    public static void main(String args[]) 
    { 
     String name=args[0]; 
     System.out.println(name); 
    } 
} 
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 
    ... 
    } 
} 
9

我喜欢这一张。简单,你必须为每个参数多个参数:

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 
+0

我很惊讶没有图书馆,这是它的优雅方式。所有其他人都会以某种方式危害您的代码(冗余代码,可变状态,额外的构造函数调用)。 –

+0

增强请求 - 您可以修改此答案以接受等于分隔符吗? :)我会猜测自己,而是你做到了。 –

1

你可以在REFCODES在refcodes-console使用refcodes-console神器。ORG:

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 =新AndConditionImpl(R,S,A,ARG1,ARG2,ARG3,ARG4,新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()); 
+1

哦,你的图书馆在许多地方都会拉。我停止计数。对不起,不会为我做。 – peterh

+0

你说得对。我修正了这个版本** 1.1.0 **刚刚发布到maven central [1]。编译时依赖不包括refcodes依赖[2]我用这个命令确定: 'mvn dependency:list -DincludeScope = compile -DexcludeScope = test |的grep -v refcodes' 卸下一个假阳性[3]根据该结果,我结束了这些依赖于版本1.1.0 ** **: '的JLine:的JLine:罐子:2.14.2:compile' 'log4j:log4j:jar:1.2.17:compile' 感谢您的输入,希望它有帮助! :-) –

+0

[1]请参阅版本1.1.0的refcodes [change-list](http://www.refcodes.org/refcodes/refcodes.org_change_list_version_1.1.0)。 [2]它们的refcodes工件有一个源代码,一个版本,全部同步发布并分解为模块化问题和模块化问题,而且全部位于https://bitbucket.org/refcodes。 [3]请参阅[为什么dependency:list ...列出测试作用域项目的传递依赖项的编译范围](http://stackoverflow.com/questions/17237281/why-does-dependencylist-dincludescope-compile-lists -compile-范围换transiti) –

1

这里是升级到共享CLI 1.3.1顺应性(取代弃用部件OptionBuilder和GnuParser)@DwB溶液。 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()); 
    } 

} 

输出:?如何在Java中解析命令行参数]

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