问题
I would like to have a printed usage help message, when option which is specified as an program argument is not valid (not available in predefined options list).
CommandLineParser parser = new BasicParser();
try {
CommandLine line = parser.parse(getOptions(), args);
}
catch( ParseException exp ) {
getLogger().info("Invalid command line option name. "+exp.getMessage());
HelpFormatter hf = new HelpFormatter();
hf.printHelp("destDir", getOptions());
return false;
}
return true;
I type as an parameter 'Test' string. I was thinking, that invalid options cause parser to throw ParseException, however it's not. How can I achieve that behaviour ? Is it possible with this library at all ? Now it just ommit paremeters which are not valid.
UPDATE Actually it throws exception when option has a '-' prefix. So '-Test' cause throwing exception, but 'Test' not. My question anyway is still valid, how to force parser to throw exception on invalid parameter
回答1:
Command lines have two types of entry other than the program name, Options (which are specified with a -
or --
) and what I will call parameters (which probably have a better name but I don't know what it is!) which don't have a prefix. For example, for ls
:
ls -la foo
The options are -l
and -a
, and parameter is foo
(the directory to list). When you parse a command line with commons-cli it only cares about the options, it ignores everything else. Which is why it doesn't fail if you add Test
(not an option) but does if you add -Test
.
回答2:
Although answer provided by adamreeve is really fine and I accept it, I've decided to extend default parser capabilities to prevent typing invalid option even without '-' or '--' symbols. I made my own custom parser :
public class StrictParser extends Parser {
@Override
protected String[] flatten(Options opts, String[] arguments, boolean stopAtNonOption) {
return arguments;
}
@Override
public CommandLine parse(Options options, String[] arguments, boolean stopAtNonOption) throws ParseException {
CommandLine cmd = null;
List<String> tokenList = Arrays.asList(flatten(getOptions(), arguments, stopAtNonOption));
ListIterator<String> iterator = tokenList.listIterator();
boolean eatTheRest = false;
setOptions(options);
cmd = super.parse(options, arguments, stopAtNonOption);
while (iterator.hasNext()) {
String token = (String) iterator.next();
if (!token.startsWith("--") && !token.startsWith("-")) {
if (stopAtNonOption) {
throw new UnrecognizedOptionException("Unrecognized option: " + token +". Every option must start with '--' or '-'", token);
}
} else {
eatTheRest = true;
}
if (eatTheRest) {
iterator.next();
}
}
return cmd;
}
}
In this solution any cli parameters typed without '--' or '-' throw UnrecognizedOptionException. This is no perfect solution, but it show how it can be done, and can be a good starting point to other solutions. For instance we could accept options without '--' and '-' but check if that option is correct. Then we need to change
if (stopAtNonOption) {
throw new UnrecognizedOptionException("Unrecognized option: " + token +". Every option must start with '--' or '-'", token);
}
to
if (stopAtNonOption) {
if(!getOptions().hasOption(token)){
throw new UnrecognizedOptionException(
"Unrecognized option: " + token, token);
}
}
(ignore this ugly three nested ifs ;)) This also accepts only one argument per option,but as I've mentioned it's only starting point to implement other modifications to default parser
回答3:
Yes you can , you have to create custom Exception like:
public class ParseException extends Exception{
ParseException(String msg){
super(msg);
}
}
And into code :
CommandLineParser parser = new BasicParser();
try {
CommandLine line = parser.parse(getOptions(), args);
}
catch( Exception exp ) {
throw new ParseException("Invalid Arguments");
}
return true;
And above method should throw
throws ParseException
So its caller if pass invalid argument will get ParseException
来源:https://stackoverflow.com/questions/40082191/why-default-parser-using-commons-cli-does-not-throw-exception-when-option-is-n