16

I used to work with Apache Commons Cli 1.2. I wanted the parser to ignore arguments if they are unknown (not added to an Options-Object).

Example (pseudocode):

Options specialOptions;
specialOptions.addOption(null, "help", false, "shows help");
specialOptions.addOption(null, "version", false, "show version");

CommandLineParser parser = new DefaultParser();
CommandLine cmd = parser.parse(options, args); //no third argument, since i dont want the program to stop parsing.
// run program with args: --help --unknown --version
// program shall parse --help AND --version, but ignore --unknown

I used this the solution by Pascal Schäfer: Can Apache Commons CLI options parser ignore unknown command-line options?

This worked fine for me on 1.2, and it works fine on 1.3.1 as well. But its deprecated. The parser I used got replaced by the DefaultParser. I looked up the functionalities, but there is no such method processOptions.

I really would like to use code that is not going to be deleted in later releases. Does anyone have an idea how to solve this problem?

leif_good
  • 376
  • 6
  • 19

3 Answers3

7

Thanks, @kjp, for the suggestion; but the solutions doesn't work for arguments with values.

I've tried improving upon kjp's solution:

public class RelaxedParser extends DefaultParser {

@Override
public CommandLine parse(final Options options, final String[] arguments) throws ParseException {
    final List<String> knownArgs = new ArrayList<>();
    for (int i = 0; i < arguments.length; i++) {
        if (options.hasOption(arguments[i])) {
            knownArgs.add(arguments[i]);
            if (i + 1 < arguments.length && options.getOption(arguments[i]).hasArg()) {
                knownArgs.add(arguments[i + 1]);
            }
        }
    }
    return super.parse(options, knownArgs.toArray(new String[0]));
}

}

aalosious
  • 578
  • 6
  • 11
3

The same approach as given in the solution by Pascal can be used here.

public class RelaxedParser extends DefaultParser {

    @Override
    public CommandLine parse(Options options, String[] arguments) throws ParseException {
        List<String> knownArguments = new ArrayList<>();
        for (String arg : arguments) {
            if (options.hasOption(arg)) {
                knownArguments.add(arg);
            }
        }
        return super.parse(options, knownArguments.toArray(new String[knownArguments.size()]));
    }
}

Or alternatively, remove unknown options from args as above and use the DefaultParser.

kjp
  • 3,086
  • 22
  • 30
  • 2
    This will not work if you want to use arguments with values, as they would have been filtered out. – Asu Jun 18 '19 at 02:08
0

This should work for your use-case:

Options options = new Options();
CommandLine commandLine = new DefaultParser().parse(options, args, true);

The important part for you is the stopAtNonOption: true:

Flag indicating how unrecognized tokens are handled. true to stop the parsing and add the remaining tokens to the args list. false to throw an exception.

Docs at https://commons.apache.org/proper/commons-cli/javadocs/api-1.3.1/org/apache/commons/cli/DefaultParser.html#stopAtNonOption

Maria Ines Parnisari
  • 16,584
  • 9
  • 85
  • 130
Olivier Grégoire
  • 33,839
  • 23
  • 96
  • 137
  • 2
    Sorry, maybe i expressed myself bad: The Method you are telling me to use doesnt solve the problem, since the programm will STOP parsing the argument, even though he does not throw an exception. For my use-case, the parsing has to go on, and the unknown argument shall only be ignored or skipped. Going to add some details to the question. Sorry for that. – leif_good Nov 23 '15 at 16:07
  • It's better to edit this answer since it's not the solution to the question, but it could be another solution for other people. – SexyNerd May 06 '17 at 00:09
  • I tried the above option and parse sends ParseException (even when the code says it shouldn't). Maybe there's a bug in DefaultParser. – JACH Dec 07 '17 at 01:11
  • 1
    Dismiss my previous comment. False sends a ParseException when an unknown option is found, which is probably not what was asked in this question. True in the other hand ignores them (and, if it is true to its name, it stops). I'm not sure if it stops completely (ignoring everything after the option was not recognized) or not. – JACH Dec 07 '17 at 01:20
  • I gave this answer an upvote. Stackoverflow won't let me remove that vote. I understoood this boolean to be "ignore unknown options". Instead it is stop parsing if an unknown option is meet. I've a single arg that targets a specific environment. This week I ran a load test where I added another command line arg to increase the amount of traffic. To my surprise I ended up targeting the default env and taking it down. Sigh. At least now I know why. – Shane Gannon Oct 01 '21 at 10:52