Parsing arguments to a Java command line program

后端 未结 9 989
孤街浪徒
孤街浪徒 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:10

    I like this one. Simple, and you can have more than one parameter for each argument:

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

    For example:

    -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)
  • 2020-12-07 21:15

    Ok, thanks to Charles Goodwin for the concept. Here is the answer:

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

    Here is @DwB solution upgraded to Commons CLI 1.3.1 compliance (replaced deprecated components OptionBuilder and GnuParser). The Apache documentation uses examples that in real life have unmarked/bare arguments but ignores them. Thanks @DwB for showing how it works.

    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:

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

    You could use the refcodes-console artifact at refcodes-console on 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 );
    

    Create your arguments parser ArgsParserImpl with your root condition:

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

    Above you define your syntax, below you invoke the parser:

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

    In case you provided some good descriptions, theArgsParser.printUsage() will even show you the pretty printed usage:

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

    In the above example all defined arguments must be passed by the user, else the parser will detect a wrong usage. In case the --test switch is to be optional (or any other argument), assign theRoot as follows:

    theRoot = new AndConditionImpl( r, s, a, arg1, arg2, arg3, arg4, new OptionalImpl( test ) );

    Then your syntax looks as follows:

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

    The full example for your case you find in the StackOverFlowExamle. You can use AND, OR, XOR conditions and any kind of nesting ... hope this helps.

    Evaluate the parsed arguments as follows: r.getValue() ); or 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() );
    
    0 讨论(0)
  • You could just do it manually.

    NB: might be better to use a HashMap instead of an inner class for the 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
    }
    
    0 讨论(0)
  • 2020-12-07 21:28

    Use the Apache Commons CLI library commandline.getArgs() to get arg1, arg2, arg3, and arg4. Here is some code:

    
    
        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 讨论(0)
提交回复
热议问题