I am writing a Java application that takes command line arguments which are processed using Apache Commons CLI with the GnuParser. For reasons that are not interesting to get into, I would like it to silently ignore unknown command line options instead of throwing a ParseException but I don't see a way to do that. I see that there is a stopAtNonOption boolean option on GnuParser.parse() but what I want is more like ignoreAtNonOption where it will keep processing options after encountering an unknown token.
I could implement my own parser to accomplish this but I'm surprised there isn't this functionality built in so I thought I'd check before going down that road.
Example code for what I'm talking about:
try { CommandLine commandLine = parser.parse(options, args); // stopAtNonOption set to true (below) is also not what I want // CommandLine commandLine = parser.parse(options, args, true); } catch (ParseException e) { LOG.error("error parsing arguments", e); throw new RuntimeException(e); }
This works for me (other parsers can be derived, too):
public class ExtendedGnuParser extends GnuParser { private boolean ignoreUnrecognizedOption; public ExtendedGnuParser(final boolean ignoreUnrecognizedOption) { this.ignoreUnrecognizedOption = ignoreUnrecognizedOption; } @Override protected void processOption(final String arg, final ListIterator iter) throws ParseException { boolean hasOption = getOptions().hasOption(arg); if (hasOption || !ignoreUnrecognizedOption) { super.processOption(arg, iter); } } }
As mentioned in a comment, the accepted solution is no more suitable because the processOption
method has been deprecated and removed.
Here's my solution:
public class ExtendedParser extends DefaultParser { private final ArrayList<String> notParsedArgs = new ArrayList<>(); public String[] getNotParsedArgs() { return notParsedArgs.toArray(new String[notParsedArgs.size()]); } @Override public CommandLine parse(Options options, String[] arguments, boolean stopAtNonOption) throws ParseException { if(stopAtNonOption) { return parse(options, arguments); } List<String> knownArguments = new ArrayList<>(); notParsedArgs.clear(); boolean nextArgument = false; for (String arg : arguments) { if (options.hasOption(arg) || nextArgument) { knownArguments.add(arg); } else { notParsedArgs.add(arg); } nextArgument = options.hasOption(arg) && options.getOption(arg).hasArg(); } return super.parse(options, knownArguments.toArray(new String[knownArguments.size()])); } }
Compared with the solution proposed by Pascal, it also checks for options with arguments and it keeps not parsed args in a separate list.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With