2013-01-13 5 views
6

So habe ich eine Options Instanz, die unter anderen Optionen hat (die isRequired() bemerken):Wie kann ich eine ParserException für erforderliche Optionen vermeiden, wenn Benutzer nur die Verwendung drucken möchte?

 options.addOption(OptionBuilder 
       .withLongOpt("seq1") 
       .withDescription("REQUIRED : blah blah") 
       .hasArg().isRequired().create()); 
     options.addOption(OptionBuilder 
       .withLongOpt("seq2") 
       .withDescription("REQUIRED : blih blih") 
       .hasArg().isRequired().create()); 
     options.addOption(new Option("?", "help", false, 
       "print this message and exit")); 

Wenn ich rufe parser.parse(args) eine Ausnahme auslöst, wenn seq1 und seq2 nicht vorhanden sind - aber ich will es meine Nachricht drucken haben und keine Ausnahme geworfen - wie man das macht? Dies wirft NPE in line.hasOption("help"), natürlich:

CommandLine line = null; 
try { 
    CommandLineParser parser = new GnuParser(); 
    // parse the command line arguments 
    line = parser.parse(options, args); 
} catch (ParseException e) { 
    if (line.hasOption("help")) { //NPE 
     usage(0); 
    } 
    System.err.println("Parsing failed. Reason: " + e.getMessage()); 
    usage(1); 
} 

private static void usage(int exitCode) { 
    // automatically generate the help statement 
    HelpFormatter formatter = new HelpFormatter(); 
    formatter.printHelp("Smith Waterman", OPTIONS, true); 
    System.exit(exitCode); 
} 
+0

Wenn der Parameter parser.parse() eine ParseException auslöst, wird kein Wert zurückgegeben. So funktionieren Java-Ausnahmen. Daher müssen Sie wahrscheinlich die Originalargumente selbst überprüfen, um zu sehen, ob die 'Hilfe'-Option bestanden wurde. – GreyBeardedGeek

+0

@GreyB: Ich weiß (beachten Sie die _natürlich _) - Ich bin mir sicher, es muss einen anderen Weg geben - eigentlich fand ich einen Workaround, aber ich hoffe, jemand kenntnisreicher wird antworten - sonst werde ich meine Problemumgehung als Antwort –

Antwort

7

Lösung von here

private static final Options OPTIONS = new Options(); 
private static final Options HELP_OPTIONS = new Options(); 
OPTIONS.addOption(OptionBuilder 
     .withLongOpt("seq1") 
     .withArgName("file1") 
     .withDescription(
       "REQUIRED : the file containing sequence 1") 
     .hasArg().isRequired().create()); 
// etc 
final Option help = new Option("?", "help", false, 
     "print this message and exit"); 
HELP_OPTIONS.addOption(help); 
OPTIONS.addOption(help); 
// later 
CommandLineParser parser = new GnuParser(); 
CommandLine line = parser.parse(HELP_OPTIONS, args, true); // true so it 
// does not throw on unrecognized options 
if (line.hasOption("help")) { 
    usage(0); // calls exit 
} 
line = parser.parse(OPTIONS, args); 

angepasst Wenn etwas elegantere kommt würde ich gerne annehmen es

+0

Das kommt irgendwie immer noch fehl wenn '?' oder '--help' am Ende hinzugefügt wird. 'command --seq1 --help' würde mir eine' MissingArgumentException' geben. Ich habe einen kleinen Check gemacht, bevor ich jetzt analysiere. – superbly

+0

@superbly: erwäge, es zu melden und den Link aus dem Bericht hier zu posten –

+0

Ich habe eine Antwort mit dem Haken hinzugefügt: http : //stackoverflow.com/a/28543094/606496 – superbly

0

Commons CLI behandelt nicht inter-Option Abhängigkeiten, wie Sie entdeckt haben. In Ihrem Fall ändert die Option --help die Anforderung für seq1 und seq2.

Die einzige echte Lösung besteht darin, alle Optionen nicht erforderlich zu machen und die Abhängigkeitsprüfung selbst durchzuführen, nachdem die Befehlszeilenanalyse abgeschlossen ist.

+0

nicht wahr - es gibt eine Weg aber ich bin nicht wirklich zufrieden - werde es aber posten wenn niemand etwas eleganteres findet –

1

Dies kann oder kann nicht nützlich sein, abhängig von Ihrer Verwendung. Mine ist wie folgt:

  • Ich habe ein Wrapper-Programm (so genannte ‚Controller‘)
  • gibt es viele Befehle (die so genannte ‚Aufgaben‘), dass der Controller
  • jeden Befehl ausführen kann, hat seinen eigenen Satz von einzigartiges Kommandozeilenargument setzt

Zum Beispiel:

$ controller startall -rsrc foo -dir bar -where baz 

das erste, was mit den Argumenten getan ist zu bestimmen, was der Befehl ist. Dafür richte ich eine TaskFactory ein, die das erste Argument betrachtet, einen führenden Bindestrich entfernt und nachschaut, ob es sich um eine bekannte Aufgabe handelt. Ich habe eine 'Hilfe' Aufgabe, die meine Benutzer können tun:

$ controller -help 

und

$ controller help 

Jede Aufgabe auch eine Hilfe-Option hat, so kann der Benutzer tun:

$ controller startall -help 

Das kann dir jedoch nicht helfen. Ich werde eine Alternative veröffentlichen.

0

Erweitern Sie Ihren gewählten Parser unbekannte Optionen zu ignorieren:

Can Apache Commons CLI options parser ignore unknown command-line options?

Und dann die Argumente zweimal analysiert, einmal für das -help Argument und einmal für die normalen Argumente. Das erste Mal durch Sie sollte es die "ignorieren" -Flag übergeben, das zweite Mal sollten Sie nicht.

Alternativ, durch die Optionen zweimal analysieren, einmal auf der Suche nach und fangen (und ignorieren) MissingOptionException und dann wieder mit den regulären Argumenten.

1

ich die folgende Überprüfung vor Parsen verwendet, um sicherzustellen, -h oder --help alles andere überstimmt.

// check if help is requested 
if (Arrays.asList(args).contains("-h") 
     || Arrays.asList(args).contains("--help")) { 
    usage(0); // print usage with exit 0 
} 
// parse options 

Nicht die schönste Lösung, aber es erfüllt meine Bedürfnisse.

Verwandte Themen