Wie analysiere ich Befehlszeilenargumente in Java?

586

Was ist eine gute Möglichkeit, Befehlszeilenargumente in Java zu analysieren?

Lindelof
quelle
4
Siehe args4j und ein detailliertes Beispiel, wie man es benutzt: martin-thoma.com/how-to-parse-command-line-arguments-in-java
Martin Thoma
Sieht so aus, als wäre ich ziemlich spät zu dieser Party gekommen, aber ich habe einen Befehlszeilen-Argument-Handler für Java geschrieben und ihn auf GitHub gestellt: MainArgsHandler . Was das Schließen des Threads betrifft, denke ich, dass dies ein sehr hilfreicher Thread ist, aber er sollte möglicherweise zur allgemeinen Programmierdiskussion auf die Stack Exchange Programmers-Site migriert werden.
Bobulous
@ RedGlyph - Es sieht so aus, als müssten SO / SE ihre Regeln vereinfachen. Die Frage hätte lauten sollen : How to parse java command line arguments?. Aber niemand möchte wirklich Code schreiben, um dies zu tun, sondern ein Werkzeug verwenden. Aber die Suche nach Werkzeugen und
Ähnlichem
6
Für die Wiedereröffnung gestimmt. @AlikElzin: In der Tat müssen sie ihren Moderationsprozess überprüfen. Ich vermute, dass es ein Abzeichen gibt, um so viele Fragen zu schließen, und dass es Moderatoren anlockt, übereifrig zu sein.
RedGlyph
8
Diese Frage ist ein Honeypot für schlechte / einzeilige Antworten und Toolempfehlungen. Es sollte geschlossen bleiben.
JAL

Antworten:

405

Guck dir diese an:

Oder rollen Sie Ihre eigenen:


Zum Beispiel ist dies , wie Sie verwenden commons-clizwei String - Argumente zu analysieren:

import org.apache.commons.cli.*;

public class Main {


    public static void main(String[] args) throws Exception {

        Options options = new Options();

        Option input = new Option("i", "input", true, "input file path");
        input.setRequired(true);
        options.addOption(input);

        Option output = new Option("o", "output", true, "output file");
        output.setRequired(true);
        options.addOption(output);

        CommandLineParser parser = new DefaultParser();
        HelpFormatter formatter = new HelpFormatter();
        CommandLine cmd;

        try {
            cmd = parser.parse(options, args);
        } catch (ParseException e) {
            System.out.println(e.getMessage());
            formatter.printHelp("utility-name", options);

            System.exit(1);
        }

        String inputFilePath = cmd.getOptionValue("input");
        String outputFilePath = cmd.getOptionValue("output");

        System.out.println(inputFilePath);
        System.out.println(outputFilePath);

    }

}

Verwendung über die Befehlszeile:

$> java -jar target/my-utility.jar -i asd                                                                                       
Missing required option: o

usage: utility-name
 -i,--input <arg>    input file path
 -o,--output <arg>   output file
Vinko Vrsalovic
quelle
40
Beachten Sie, dass die Apache-CLI im Gegensatz zu vielen anderen Apache-Bibliotheken keine Abhängigkeiten aufweist.
Vladimir Dyuzhev
9
Der einzige Nachteil vieler Apache-Commons-Projekte ist, dass sie immer weniger Commits erhalten und schließlich veraltet sind.
Brett Ryan
4
Auf der Seite "Verwendungsszenarien" für das Apache CLI-Projekt erfahren
Brad Parks
Ich nehme nicht an, dass es eine genau wie Args4J / JCommander gibt, außer wo Sie eine Schnittstelle definieren und die Methoden kommentieren? Ich habe es nie geschafft, Klassen zu lieben, die private Felder "gruselig initialisieren" ...
gruselig Trejkaz
5
@RemkoPopma deine Picocli-Bibliothek sieht einfach toll aus und danke, dass du es wirklich getan hast. Aber ich betrachte das, was Sie hier und in anderen Posts tun (akzeptierte Antworten bearbeiten und Ihre Bibliothek oben bewerben, ohne zu offenbaren, dass es sich um eine Bearbeitung handelt, die nicht vom ursprünglichen Autor des Posts stammt und Ihre Bibliothek ist), als einen schrecklichen, schrecklichen Missbrauch Ihrer Moderationsfähigkeiten. Dies auf andere Mods hinweisen.
Alexander Malakhov
312

Schauen Sie sich den neueren JCommander an .

Ich habe es geschaffen. Ich freue mich über Fragen oder Feature-Anfragen.

Cedric Beust
quelle
7
Ich bin froh, dass du JCommander magst :-) Ich wollte der Behandlung der Flags nicht zu viel Semantik hinzufügen, deshalb musst du nur Synonyme in die von dir verwendeten Anmerkungen einfügen: @Parameter (names = {"-h", "- -help "}) Ich dachte, es ist ein vernünftiger Kompromiss.
Cedric Beust
14
Tolles Werkzeug. Leistungsstark, flexibel und Sie müssen sich nicht mit den nervigen, traditionellen Optionsparsern auseinandersetzen.
Ian Gilham
3
Ja, ich glaube, ich hätte meinen eigenen Befehlszeilenargument-Parser genauso geschrieben, wie Sie JCommander geschrieben haben. Gute Arbeit.
SRG
9
@ CedricBeust, dies ist eine brillante Bibliothek, ich danke Ihnen vielmals. Da wir unsere eigenen Args-Klassen definieren können, die dann ohne Abhängigkeit von einer Bibliotheksklasse weitergegeben werden können, ist sie äußerst flexibel.
Brett Ryan
2
bläst die Konkurrenz aus dem Wasser!
Marcus Junius Brutus
235

Ich habe versucht, eine Liste von Java CLI-Parsern zu führen .

Lexikon
quelle
7
@ Ben Flynn hehe, da sind einige ziemlich überraschend und interessant geformte Räder drin. Ich denke, es ist eine weitgehend harmlose Art zu zeigen, dass es viel mehr als eine Möglichkeit gibt, dies zu tun!
Lexicalscope
14
Ich stelle fest, dass der Autor von JOpt Simple eine sehr ähnliche Liste führt! Wir benötigen Text, um diese Listen in eine Tabelle umzuwandeln, in der Funktionen und Sonderziele aufgelistet sind, damit wir armen Benutzer eine fundierte Auswahl treffen können.
Tom Anderson
1
Ich habe Rop - github.com/ryenus/rop erstellt , eine auf Anmerkungen basierende Lösung, mit der Sie Befehle und Optionen über einfache Klassen und Felder deklarieren können. Dies ist eine deklarative Methode zum Erstellen von Befehlszeilenparsern. Es kann entweder Git (Single-cmd) oder Maven (Multi-cmd) wie Apps erstellen.
Ryenus
8
Die meisten der aufgelisteten Projekte sind im Wesentlichen Abbruchware. Nachdem ich die Liste durchgesehen habe, würde ich sagen, dass die großen Hitter, die aktiv gepflegt und beliebt sind, Commons-Cli, JCommander, Args4J, Jopt-Simple und Picocli zu sein scheinen. Entschuldigung an die Autoren von Dingen wie argparse4j und cli-parser - ich musste ein etwas willkürliches Ranking erstellen und eine der fünf besten auswählen. Offensichtlich sind andere Projekte in der Liste beliebt und befinden sich ebenfalls noch in der aktiven Entwicklung.
George Hawkins
2
Ich fordere jemanden auf, das Datum der letzten stabilen Veröffentlichung jedes Parsers anzugeben.
Schlitten
50

Es ist 2020, Zeit, es besser zu machen als Commons CLI ... :-)

Sollten Sie Ihren eigenen Java-Befehlszeilenparser erstellen oder eine Bibliothek verwenden?

Viele kleine Utility-ähnliche Anwendungen führen wahrscheinlich eine eigene Befehlszeilenanalyse durch, um die zusätzliche externe Abhängigkeit zu vermeiden. Picocli kann eine interessante Alternative sein.

Picocli ist eine moderne Bibliothek und ein Framework, mit dem Sie mühelos leistungsstarke, benutzerfreundliche und GraalVM-fähige Befehlszeilen-Apps erstellen können. Es befindet sich in einer Quelldatei, sodass Apps es als Quelle einschließen können, um das Hinzufügen einer Abhängigkeit zu vermeiden.

Es unterstützt Farben, automatische Vervollständigung, Unterbefehle und mehr. Geschrieben in Java, verwendbar von Groovy, Kotlin, Scala usw.

Minimale Hilfe bei ANSI-Farben

Eigenschaften:

  • Annotationsbasiert: deklarativ , vermeidet Doppelarbeit und drückt die Absicht des Programmierers aus
  • Praktisch: Analysieren Sie Benutzereingaben und führen Sie Ihre Geschäftslogik mit einer Codezeile aus
  • Alles stark getippt - Befehlszeilenoptionen sowie Positionsparameter
  • POSIX gruppierte kurze Optionen ( <command> -xvfInputFilesowie<command> -x -v -f InputFile )
  • Feinkörnige Steuerung : Ein Aritätsmodell, das eine minimale, maximale und variable Anzahl von Parametern zulässt, z "1..*"."3..5"
  • Unterbefehle (können beliebig tief verschachtelt werden)
  • Funktionsreich : zusammensetzbare Arg-Gruppen, Aufteilen von zitierten Args, wiederholbare Unterbefehle und vieles mehr
  • Benutzerfreundlich : Die Nachricht zur Verwendungshilfe verwendet Farben, um wichtige Elemente wie Optionsnamen aus dem Rest der Verwendungshilfe zu kontrastieren und die kognitive Belastung zu verringern des Benutzers
  • Verteilen Sie Ihre App als natives GraalVM-Image
  • Funktioniert mit Java 5 und höher
  • Umfangreiche und sorgfältige Dokumentation

Die Verwendungshilfemeldung kann einfach mit Anmerkungen angepasst werden (ohne Programmierung). Zum Beispiel:

Hilfemeldung zur erweiterten Verwendung( Quelle )

Ich konnte nicht widerstehen, einen weiteren Screenshot hinzuzufügen, um zu zeigen, welche Verwendungshilfemeldungen möglich sind. Die Hilfe zur Verwendung ist das Gesicht Ihrer Anwendung. Seien Sie also kreativ und haben Sie Spaß!

Picocli-Demo

Haftungsausschluss: Ich habe picocli erstellt. Feedback oder Fragen sind sehr willkommen.

Remko Popma
quelle
5
Einfach genial! Es ist eine Schande, dass diese Antwort unten vergraben ist. Apache Commons CLI ist ausführlich, fehlerhaft und wurde seit langem nicht mehr aktualisiert. Und ich möchte den CLI-Parser von Google nicht verwenden, da ich keine gezielten Anzeigen basierend auf dem Verwendungsverlauf meiner Befehlszeilenargumente möchte. Aber es sieht sowieso etwas ausführlicher aus als Picocli.
Pete
2
Ich habe @Pete hier unterstützt ... Ich habe die obige Liste durchgesehen, was eine völlige Zeitverschwendung war, da diese unten vergraben ist. Dies sollte die beste Antwort für eine Meile sein. Gut gemacht! Meine Anforderungen konnten von Apache CLI oder den meisten dieser anderen Parser nicht abgedeckt werden. Sie waren selbst für Picocli eine Herausforderung, aber es konnte mir die Syntax / das Verhalten, die ich wollte, am nächsten bringen und war flexibel genug, um das zu hacken, was ich wirklich brauchte. Als Bonus sieht es dank des ANSI-Materials großartig aus.
Shai Almog
@ShaiAlmog Die am häufigsten gewählte Antwort ist 10 Jahre alt und veraltet. Ich bin damit einverstanden, dass die Empfehlung von Commons CLI im Jahr 2019 meiner Meinung nach irreführend ist. Bitte überlegen Sie , die Top-Antwort neu zu schreiben , um sie aktueller zu machen.
Remko Popma
Ich sehe, dass du das schon versucht hast, ich glaube nicht, dass das auch für mich funktionieren wird ... Wenn du einen Namen wie 1Picoli gewählt hättest, hätten wir die 3. Antwort alphabetisch sortieren können ;-)
Shai Almog
Ich denke, der Grund, warum meine Änderung rückgängig gemacht wurde, ist, dass ich meine Zugehörigkeit nicht offengelegt habe (dass ich der Autor bin). Andere Leute sollten dieses Problem nicht haben.
Remko Popma
23

Ich habe JOpt verwendet und fand es ziemlich praktisch: http://jopt-simple.sourceforge.net/

Auf der Startseite finden Sie außerdem eine Liste mit ca. 8 alternativen Bibliotheken. Schauen Sie sich diese an und wählen Sie die aus, die Ihren Anforderungen am besten entspricht.

GaryF
quelle
21

Jemand hat mich in letzter Zeit auf args4j hingewiesen, das auf Anmerkungen basiert. Ich mag es wirklich!

André
quelle
1
+1 für Args4J! Sehr menschenfreundlich, flexibel und verständlich. Ich denke, es sollte die Standardbibliothek zum Erstellen von Java CLI-Apps sein.
Zearin
Großartig, dass es ungeordneten (nach Feldreihenfolge sortierten) Verwendungsdruck verarbeiten kann, was JCommander nicht kann, und es ist flexibler.
Daniel Hári
@ DanielHári Nur zur Information, diese Funktion wurde in JCommander hinzugefügt (irgendwann Ende Februar 2017).
Nathan
9

Dies ist Googles Befehlszeilen-Analysebibliothek, die im Rahmen des Bazel-Projekts als Open-Source-Bibliothek bereitgestellt wird. Persönlich denke ich, dass es das beste ist und viel einfacher als Apache CLI.

https://github.com/pcj/google-options

Installation

Bazel

maven_jar(
    name = "com_github_pcj_google_options",
    artifact = "com.github.pcj:google-options:jar:1.0.0",
    sha1 = "85d54fe6771e5ff0d54827b0a3315c3e12fdd0c7",
)

Gradle

dependencies {
  compile 'com.github.pcj:google-options:1.0.0'
}

Maven

<dependency>
  <groupId>com.github.pcj</groupId>
  <artifactId>google-options</artifactId>
  <version>1.0.0</version>
</dependency>

Verwendungszweck

Erstellen Sie eine Klasse, OptionsBasedie Ihre @Option(n) erweitert und definiert .

package example;

import com.google.devtools.common.options.Option;
import com.google.devtools.common.options.OptionsBase;

import java.util.List;

/**
 * Command-line options definition for example server.
 */
public class ServerOptions extends OptionsBase {

  @Option(
      name = "help",
      abbrev = 'h',
      help = "Prints usage info.",
      defaultValue = "true"
    )
  public boolean help;

  @Option(
      name = "host",
      abbrev = 'o',
      help = "The server host.",
      category = "startup",
      defaultValue = ""
  )
  public String host;

  @Option(
    name = "port",
    abbrev = 'p',
    help = "The server port.",
    category = "startup",
    defaultValue = "8080"
    )
    public int port;

  @Option(
    name = "dir",
    abbrev = 'd',
    help = "Name of directory to serve static files.",
    category = "startup",
    allowMultiple = true,
    defaultValue = ""
    )
    public List<String> dirs;

}

Analysieren Sie die Argumente und verwenden Sie sie.

package example;

import com.google.devtools.common.options.OptionsParser;
import java.util.Collections;

public class Server {

  public static void main(String[] args) {
    OptionsParser parser = OptionsParser.newOptionsParser(ServerOptions.class);
    parser.parseAndExitUponError(args);
    ServerOptions options = parser.getOptions(ServerOptions.class);
    if (options.host.isEmpty() || options.port < 0 || options.dirs.isEmpty()) {
      printUsage(parser);
      return;
    }

    System.out.format("Starting server at %s:%d...\n", options.host, options.port);
    for (String dirname : options.dirs) {
      System.out.format("\\--> Serving static files at <%s>\n", dirname);
    }
  }

  private static void printUsage(OptionsParser parser) {
    System.out.println("Usage: java -jar server.jar OPTIONS");
    System.out.println(parser.describeOptions(Collections.<String, String>emptyMap(),
                                              OptionsParser.HelpVerbosity.LONG));
  }

}

https://github.com/pcj/google-options

Paul
quelle
Hallo Paul. Wenn ich Ihre Antwort oder Ihre Projektdokumentation lese, habe ich keine Ahnung, welche Art von Befehlszeile damit umgehen kann. Zum Beispiel können Sie so etwas bereitstellen myexecutable -c file.json -d 42 --outdir ./out. Und ich sehe nicht, wie Sie kurze / lange / Beschreibungsoptionen definieren ... Cheers
olibre
8

Schauen Sie sich das Commons CLI- Projekt an, viele gute Sachen drin.

Marc Novakowski
quelle
8

Ja.

Ich denke, Sie suchen nach so etwas: http://commons.apache.org/cli

Die Apache Commons CLI-Bibliothek bietet eine API für die Verarbeitung von Befehlszeilenschnittstellen.

OscarRyz
quelle
7

Ich weiß, dass die meisten Leute hier 10 Millionen Gründe finden werden, warum sie meinen Weg nicht mögen, aber egal. Ich mag es, die Dinge einfach zu halten, also trenne ich den Schlüssel einfach mit einem '=' vom Wert und speichere sie in einer HashMap wie folgt:

Map<String, String> argsMap = new HashMap<>();
for (String arg: args) {
    String[] parts = arg.split("=");
    argsMap.put(parts[0], parts[1]);
} 

Sie können jederzeit eine Liste mit den erwarteten Argumenten führen, um dem Benutzer zu helfen, falls er ein Argument vergessen oder ein falsches verwendet hat. Wenn Sie jedoch zu viele Funktionen wünschen, ist diese Lösung ohnehin nichts für Sie.

John Koumarelas
quelle
7

Vielleicht diese

  • JArgs-Parsing-Suite für Befehlszeilenoptionen für Java - Dieses winzige Projekt bietet eine praktische, kompakte, vorgefertigte und umfassend dokumentierte Suite von Parsern für Befehlszeilenoptionen für Java-Programmierer. Zunächst wird eine Analyse angeboten, die mit 'getopt' im GNU-Stil kompatibel ist.

  • ritopt, der ultimative Optionsparser für Java - Obwohl mehrere Befehlszeilenoptionsstandards festgelegt wurden, folgt ritopt den im opt-Paket vorgeschriebenen Konventionen.

Mepcotterell
quelle
6

Vielleicht finden Sie diesen Meta-Artikel des Unglücks als Ausgangspunkt interessant:

http://furiouspurpose.blogspot.com/2008/07/command-line-parsing-libraries-for-java.html

Alex Miller
quelle
2
Dieser Typ ist ziemlich nutzlos "Commons CLI Anscheinend die älteste der Optionen hier und bekommt von Kommentatoren nicht viel Respekt, also habe ich mir das nicht wirklich genau angesehen ...", aber trotzdem danke für den Link.
James McMahon
5

Ich habe einen anderen geschrieben: http://argparse4j.sourceforge.net/

Argparse4j ist eine Befehlszeilenargument-Parser-Bibliothek für Java, die auf Pythons Argparse basiert.

Tatsuhiro Tsujikawa
quelle
Willkommen bei Stack Overflow! Vielen Dank für Ihre Antwort! Bitte lesen Sie die FAQ zur Eigenwerbung sorgfältig durch.
Andrew Barber
4

Airline @ Github sieht gut aus. Es basiert auf Anmerkungen und versucht, Git-Befehlszeilenstrukturen zu emulieren.

cthiebaud
quelle
4

Wenn Sie Spring Boot bereits verwenden, ist die Argumentanalyse sofort einsatzbereit.

Wenn Sie nach dem Start etwas ausführen möchten, implementieren Sie die ApplicationRunnerSchnittstelle:

@SpringBootApplication
public class Application implements ApplicationRunner {

  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }

  @Override
  public void run(ApplicationArguments args) {
    args.containsOption("my-flag-option"); // test if --my-flag-option was set
    args.getOptionValues("my-option");     // returns values of --my-option=value1 --my-option=value2 
    args.getOptionNames();                 // returns a list of all available options
    // do something with your args
  }
}

Ihre run Methode wird aufgerufen, nachdem der Kontext erfolgreich gestartet wurde.

Wenn Sie Zugriff auf die Argumente benötigen, bevor Sie Ihren Anwendungskontext starten, können Sie die Anwendungsargumente einfach manuell analysieren:

@SpringBootApplication
public class Application implements ApplicationRunner {

  public static void main(String[] args) {
    ApplicationArguments arguments = new DefaultApplicationArguments(args);
    // do whatever you like with your arguments
    // see above ...
    SpringApplication.run(Application.class, args);
  }

}

Und schließlich, wenn Sie Zugriff auf Ihre Argumente in einer Bean benötigen, fügen Sie einfach Folgendes ein ApplicationArguments:

@Component
public class MyBean {

   @Autowired
   private ApplicationArguments arguments;

   // ...
}
Stefan Haberl
quelle
Das ist fantastisch :).
John Humphreys - w00te
3

Argparse4j ist das Beste, was ich gefunden habe. Es ahmt Pythons Argparse-Bibliothek nach, die sehr praktisch und mächtig ist.

Trismegistos
quelle
2

Wenn Sie etwas Leichtes (JAR-Größe ~ 20 KB) und eine einfache Verwendung wünschen, können Sie den Argument-Parser ausprobieren . Es kann in den meisten Anwendungsfällen verwendet werden, unterstützt die Angabe von Arrays im Argument und ist von keiner anderen Bibliothek abhängig. Es funktioniert für Java 1.5 oder höher. Der folgende Auszug zeigt ein Beispiel für die Verwendung:

public static void main(String[] args) {
    String usage = "--day|-d day --mon|-m month [--year|-y year][--dir|-ds directoriesToSearch]";
    ArgumentParser argParser = new ArgumentParser(usage, InputData.class);
    InputData inputData = (InputData) argParser.parse(args);
    showData(inputData);

    new StatsGenerator().generateStats(inputData);
}

Weitere Beispiele finden Sie hier

Himanshu Shekhar
quelle
1
Link ist tot. Hast du dein Projekt getötet? :-(
beldaz
2

Ich würde die Verwendung der Apache Common CLIBibliothek nicht empfehlen , da sie nicht threadsicher ist.

Es verwendet statusbehaftete Klassen mit statischen Variablen und Methoden für interne Arbeiten (z. B. OptionBuilder) und sollte nur in stark kontrollierten Situationen mit einem Thread verwendet werden.

Jakub
quelle
18
Beachten Sie, dass die CLI-Bibliothek nicht threadsicher ist. Ich würde jedoch davon ausgehen, dass das Parsen der Befehlszeile normalerweise in einem einzelnen Thread während des Anwendungsstarts erfolgt und dann abhängig von den Parametern möglicherweise andere Threads gestartet werden.
Alexey Ivanov
0

Wie einer der zuvor erwähnten Kommentare ( https://github.com/pcj/google-options ) wäre zunächst eine gute Wahl.

Eine Sache, die ich hinzufügen möchte, ist:

1) Wenn Sie auf einen Parser-Reflexionsfehler stoßen, versuchen Sie bitte, eine neuere Version der Guave zu verwenden. in meinem Fall:

maven_jar(
    name = "com_google_guava_guava",
    artifact = "com.google.guava:guava:19.0",
    server = "maven2_server",
)

maven_jar(
    name = "com_github_pcj_google_options",
    artifact = "com.github.pcj:google-options:jar:1.0.0",
    server = "maven2_server",
)

maven_server(
    name = "maven2_server",
    url = "http://central.maven.org/maven2/",
)

2) Beim Ausführen der Befehlszeile:

bazel run path/to/your:project -- --var1 something --var2 something -v something

3) Wenn Sie Hilfe bei der Verwendung benötigen, geben Sie einfach Folgendes ein:

bazel run path/to/your:project -- --help
Stevens
quelle
-1

Für Spring-Benutzer sollten wir auch https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/env/SimpleCommandLinePropertySource.html und seinen Zwillingsbruder https: //docs.spring erwähnen .io / spring / docs / current / javadoc-api / org / springframework / core / env / JOptCommandLinePropertySource.html (JOpt-Implementierung derselben Funktionalität). Der Vorteil in Spring ist, dass Sie die Befehlszeilenargumente direkt an Attribute binden können. Hier finden Sie ein Beispiel: https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/env/ CommandLinePropertySource.html

Pierluigi Vernetto
quelle