Parsing arguments to a Java command line program

后端 未结 9 990
孤街浪徒
孤街浪徒 2020-12-07 20:37

What if I wanted to parse this:

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

And the result I want in my program is:

相关标签:
9条回答
  • 2020-12-07 21:29

    I realize that the question mentions a preference for Commons CLI, but I guess that when this question was asked, there was not much choice in terms of Java command line parsing libraries. But nine years later, in 2020, would you not rather write code like the below?

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

    Execute by running the command in the question:

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

    What I like about this code is that it is:

    • compact - no boilerplate
    • declarative - using annotations instead of a builder API
    • strongly typed - annotated fields can be any type, not just String
    • no duplication - option declaration and getting parse result are together in the annotated field
    • clear - the annotations express the intention better than imperative code
    • separation of concerns - the business logic in the call method is free of parsing-related logic
    • convenient - one line of code in main wires up the parser and runs the business logic in the Callable
    • powerful - automatic usage and version help with the built-in --help and --version options
    • user-friendly - usage help message uses colors to contrast important elements like option names from the rest of the usage help to reduce the cognitive load on the user

    The above functionality is only part of what you get when you use the picocli (https://picocli.info) library.

    Now, bear in mind that I am totally, completely, and utterly biased, being the author of picocli. :-) But I do believe that in 2020 we have better alternatives for building a command line apps than Commons CLI.

    0 讨论(0)
  • 2020-12-07 21:30

    You could use https://github.com/jankroken/commandline , here's how to do that:

    To make this example work, I must make assumptions about what the arguments means - just picking something here...

    -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
    

    this can then be set up this way:

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

    and then in the main method, you can just do:

    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
        ...
      }
    }
    
    0 讨论(0)
  • 2020-12-07 21:31

    Simple code for command line in java:

    class CMDLineArgument
    {
        public static void main(String args[])
        {
            String name=args[0];
            System.out.println(name);
        }
    }
    
    0 讨论(0)
提交回复
热议问题