2011-09-07 38 views
33

gì nếu tôi muốn phân tích cú pháp này:luận Parsing đến một chương trình Java dòng lệnh

java MyProgram -r opt1 -S opt2 arg1 arg2 arg3 arg4 --test -A opt3 

Và kết quả tôi muốn trong chương trình của tôi là:

regular Java args[] of size=4 
org.apache.commons.cli.Options[] of size=3 
org.apache.commons.cli.Options[] #2 of size=1 

Tôi muốn sử dụng Apache Commons CLI, nhưng tài liệu không rõ ràng về trường hợp tôi trình bày ở trên. Cụ thể, các tài liệu không cho bạn biết làm thế nào để xử lý tùy chọn loại thứ 3 tôi chỉ định dưới đây:

1. options with a "-" char 
2. options with a "--" char 
3. options without any marker, or "bare args" 

Tôi mong rằng Apache Commons CLI sẽ làm việc nhưng vẫn có thể vượt qua args thường xuyên đến chương trình nếu những người không có tiền tố tùy chọn. Có lẽ nó không nhưng tài liệu không nói như vậy khi tôi đọc qua nó ...

+1

có thể trùng lặp của (http://stackoverflow.com/questions/367706/how-to-parse-command- line-arguments-in-java) – xenteros

Trả lời

19

Bạn chỉ có thể làm điều đó theo cách thủ công.

NB: có thể tốt hơn để sử dụng HashMap thay vì lớp bên trong cho 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

Bạn nên kiểm tra độ dài của args [i]! –

+0

Tôi vừa nhập vào! Bạn cũng có thể sử dụng một bảng băm thay vì một câu lệnh switch nếu bạn muốn được ưa thích. – IslandCow

+0

@Jon Bright tốt hơn? –

0

Ok, cảm ơn Charles Goodwin về khái niệm này. Dưới đây là câu trả lời:

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

Nó vẫn không hoàn toàn đúng vì bạn không lưu trữ kết hợp '-flag opt'. –

+0

Tôi đã viết nó ra như là một giải pháp Beanshell: http: // stackoverflow.com/questions/7356979/java-beanshell-scripting-with-args-to-the-the-chương trình – djangofan

44

Sử dụng Apache Commons CLI library commandline.getArgs() để có được arg1, arg2, arg3, và arg4. Dưới đây là một số mã:



    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

một số phương pháp tiếp cận trong câu trả lời này không còn được hỗ trợ. ví dụ cho phiên bản CLI hiện tại: https://commons.apache.org/proper/commons-cli/usage.html – stuart

0

mã đơn giản cho dòng lệnh trong java:

class CMDLineArgument 
{ 
    public static void main(String args[]) 
    { 
     String name=args[0]; 
     System.out.println(name); 
    } 
} 
2

Bạn có thể sử dụng https://github.com/jankroken/commandline, dưới đây là cách để làm điều đó:

Để làm cho công việc ví dụ này, tôi phải đưa ra các giả định về ý nghĩa của các đối số - chỉ cần chọn một cái gì đó ở đây ...

-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 

này sau đó có thể được thiết lập theo cách này:

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

và sau đó trong phương thức main, bạn chỉ có thể làm:

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

Tôi thích thế này. Đơn giản và bạn có có nhiều hơn một tham số cho mỗi đối số:

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

Ví dụ:

-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

Tôi ngạc nhiên vì không có thư viện nào ở đó, điều đó có vẻ thanh lịch. Tất cả những người khác thỏa hiệp mã của bạn theo cách này hay cách khác (mã dự phòng, trạng thái có thể thay đổi, các cuộc gọi hàm tạo bổ sung). –

+0

Yêu cầu nâng cao - bạn có thể sửa đổi câu trả lời này để chấp nhận dấu phân cách bằng không? :) Tôi đoán bản thân mình nhưng thay vì bạn làm điều đó. –

1

Bạn có thể sử dụng refcodes-console tạo tác tại refcodes-console trên REFCODES.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); 

Tạo lập luận của bạn phân tích cú pháp ArgsParserImpl với điều kiện gốc của bạn:

ArgsParser theArgsParser = new ArgsParserImpl(theRoot); 
theArgsParser.setName("MyProgramm"); 
theArgsParser.setSyntaxNotation(SyntaxNotation.GNU_POSIX); 

Trên bạn xác định cú pháp của bạn, dưới đây bạn gọi phân tích cú pháp:

theArgsParser.printUsage(); 
theArgsParser.printSeparatorLn(); 
theArgsParser.printOptions(); 
theArgsParser.evalArgs(new String[] { 
    "-r", "RRRRR", "-S", "SSSSS", "11111", "22222", "33333", "44444", 
    "--test", "-A", "AAAAA" 
}); 

Trong trường hợp bạn cung cấp một số mô tả tốt, theArgsParser.printUsage() thậm chí sẽ hiển thị cho bạn mức sử dụng được in đẹp:

Usage: MyProgramm -r <opt1> -S <opt2> -A <opt3> arg1 arg2 arg3 arg4 --test 

Trong ví dụ trên tất cả đối số định nghĩa phải được thông qua bởi người sử dụng, nếu không phân tích cú pháp sẽ phát hiện một cách sử dụng sai. Trong trường hợp --test tắc là phải tùy chọn (hoặc bất kỳ lý lẽ khác), gán theRoot như sau:

theRoot = new AndConditionImpl (r, s, a, arg1, arg2, arg3, arg4, mới OptionalImpl (kiểm tra));

Sau đó, cú pháp của bạn trông như sau:

Usage: MyProgramm -r <opt1> -S <opt2> -A <opt3> arg1 arg2 arg3 arg4 [--test] 

Các ví dụ đầy đủ đối với trường hợp của bạn, bạn tìm thấy trong StackOverFlowExamle. Bạn có thể sử dụng các điều kiện AND, OR, XOR và bất kỳ loại làm tổ nào ... hy vọng điều này sẽ hữu ích.

Đánh giá các đối số phân tích cú pháp như sau: r.getValue()); hoặc 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

Oh boy thư viện của bạn kéo trong nhiều deps. Tôi ngừng đếm. Xin lỗi, sẽ không làm cho tôi. – peterh

+0

Bạn nói đúng. Tôi đã sửa lỗi này với phiên bản ** 1.1.0 ** được phát hành ngay bây giờ cho maven central [1]. Các phụ thuộc thời gian biên dịch không bao gồm các phụ thuộc mã hóa [2] Tôi xác định bằng lệnh này: 'mvn dependency: list -DincludeScope = compile -DexcludeScope = test | grep -v refcodes' Xóa một số dương tính giả [3] khỏi kết quả, tôi kết thúc với những phụ thuộc đó cho phiên bản ** 1.1.0 **: 'jline: jline: jar: 2.14.2: compile' 'log4j: log4j: jar: 1.2.17: biên dịch' Cảm ơn bạn đã nhập và hy vọng nó sẽ giúp bạn! :-) –

+0

[1] Xem mã refcodes [danh sách thay đổi] (http://www.refcodes.org/refcodes/refcodes.org_change_list_version_1.1.0) cho phiên bản 1.1.0. [2] Các tạo phẩm mã hóa của chúng là một nguồn, một phiên bản, tất cả được phát hành đồng bộ và được chia thành các mô-đun như tách mối quan tâm và mô đun hóa, hơn nữa tất cả được đặt tại https://bitbucket.org/refcodes. [3] Xem [Tại sao danh sách phụ thuộc: danh sách ... biên dịch phạm vi cho phụ thuộc transitive của các mục phạm vi kiểm tra] (http://stackoverflow.com/questions/17237281/why-does-dependencylist-dincludescope-compile-lists -compile-scope-for-transiti) –

1

Đây là giải pháp @DwB nâng cấp lên Commons CLI 1.3.1 tuân thủ (các thành phần bị phản đối thay OptionBuilder và GnuParser). Tài liệu Apache sử dụng các ví dụ mà trong cuộc sống thực có các đối số không được đánh dấu/trần nhưng bỏ qua chúng. Cảm ơn @ DWB cho thấy nó hoạt động như thế nào.

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

} 

Output: [? Làm thế nào để phân tích đối số dòng lệnh trong 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 
Các vấn đề liên quan