2016-10-17 18 views
1

当指定为程序参数的选项无效时(在预定义的选项列表中不可用),我想要打印使用帮助消息。为什么默认语法分析器(使用commons-cli)在选项无法识别时不会抛出异常?

 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; 

我输入参数'Test'字符串。我在想,无效的选项会导致解析器抛出ParseException,但事实并非如此。我如何实现这一行为?完全可以用这个库吗?现在它只是省略了无效的参数。

UPDATE 实际上,当选项带有' - '前缀时,它会抛出异常。所以'测试'会引发异常,但'测试'不是。我的问题反正仍然是有效的,如何强制解析器抛出异常的无效参数

回答

1

的命令行有两种类型的条目比程序名称,选项(这是一个---指定)和我所说的参数(这可能有一个更好的名字,但我不知道这是什么其他是!),它没有前缀。例如,对于ls

ls -la foo

选项是-l-a和参数是foo(该目录列出)。当你用commons-cli解析一个命令行时,它只关心关心这些选项,它忽略了其他的一切。这就是为什么它不会失败,如果你添加Test(不是一个选项),但如果你添加-Test

+0

好吧,我理解这一点,但我认为在commons-cli库中我将能够验证所有命令行参数 –

+0

可悲的是,正如我所知:(这就是为什么你可以经常告诉什么时候使用commons-cli的原因 - 因为一切都是'--'选项:) – adamreeve

-1

是的,你可以,你必须创建自定义的异常,如:

public class ParseException extends Exception{ 
     ParseException(String msg){ 
      super(msg); 
     } 
} 

而进入代码:

CommandLineParser parser = new BasicParser(); 
    try { 
     CommandLine line = parser.parse(getOptions(), args); 
    } 
    catch(Exception exp) { 
     throw new ParseException("Invalid Arguments"); 
    }  
    return true; 

而且上面的方法应该抛出

throws ParseException 

所以它的调用者,如果通过无效的参数会得到霸rseException

+0

您的解决方案更像是定义新的异常。但在我的情况下,当args包含无效选项时,ParseException不是从parse方法抛出。 –

+0

@ArturSkrzydło请仔细阅读答案的第二部分,其中包含修改代码的答案和答案的第三部分,显示调用方法 –

+0

时您创建了新的异常并在ParseExcpetion从解析方法抛出时抛出它。在这种情况下它没有任何意义,因为当我定义无效的参数时,我从来没有达到catch语句。 –

0

虽然adamreeve提供的答案非常好,我接受它,但我决定扩展默认分析器功能,以防止在没有' - '或' - '符号的情况下输入无效选项。我做了我自己的自定义解析器:

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

在这种解决方案,无需任何类型CLI参数“ - ”或“ - ”扔UnrecognizedOptionException。这不是完美的解决方案,但它展示了如何完成,并且可以成为其他解决方案的良好起点。例如,我们可以接受没有' - '和' - '的选项,但检查该选项是否正确。然后,我们需要改变

 if (stopAtNonOption) { 
       throw new UnrecognizedOptionException("Unrecognized option: " + token +". Every option must start with '--' or '-'", token); 
     } 

 if (stopAtNonOption) {     
      if(!getOptions().hasOption(token)){      
       throw new UnrecognizedOptionException(
         "Unrecognized option: " + token, token); 
      } 
     } 

(忽略这个丑陋的三个嵌套IFS;)) 这也接受每个选项只有一个参数,但正如我已经提到它只有起点实施对默认分析器的其他修改

相关问题