¿Cómo analizo los argumentos de la línea de comandos en Java?

586

¿Cuál es una buena forma de analizar argumentos de línea de comandos en Java?

lindelof
fuente
44
Vea args4j y un ejemplo detallado de cómo usarlo: martin-thoma.com/how-to-parse-command-line-arguments-in-java
Martin Thoma
Parece que llego bastante tarde a esta fiesta, pero escribí un controlador de argumentos de línea de comandos para Java y lo puse en GitHub: MainArgsHandler . En cuanto al hilo que se está cerrando, creo que este es un hilo muy útil, pero posiblemente debería migrarse al sitio de Stack Exchange Programmers para una discusión general de programación.
Bobulous
@RedGlyph: parece que SO / SE necesita simplificar sus reglas. La pregunta debería haber sido: How to parse java command line arguments?. Pero nadie realmente quiere escribir código para hacer esto, sino usar una herramienta. Pero la búsqueda de herramientas y
similares
66
Votado por reapertura. @AlikElzin: De hecho, necesitan revisar su proceso de moderación. Sospecho que hay una insignia para cerrar tantas preguntas, y que atrae a los que quieren ser moderadores a ser demasiado celosos.
RedGlyph
8
Esta pregunta es un honeypot para respuestas malas / de una línea y recomendaciones de herramientas. Debería permanecer cerrado.
JAL

Respuestas:

405

Mira esto:

O rueda el tuyo:


Por ejemplo, así es como se utilizan commons-clipara analizar 2 argumentos de cadena:

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

    }

}

uso desde la línea de comando:

$> 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
fuente
40
Tenga en cuenta que, a diferencia de muchas otras bibliotecas de Apache, la CLI de Apache no tiene dependencias.
Vladimir Dyuzhev
99
El único inconveniente de muchos proyectos de apache-commons es que reciben cada vez menos compromisos y, finalmente, terminan obsoletos.
Brett Ryan
44
Aquí está la página "Escenarios de uso" para el proyecto CLI de Apache, que detalla cómo comenzar a usarlo rápidamente: commons.apache.org/cli/usage.html
Brad Parks
No creo que haya uno exactamente como Args4J / JCommander, excepto donde define una interfaz y anota los métodos. Nunca he sido capaz de crecer aficionado a las clases que se "Spooky" Inicializa los campos privados ...
Trejkaz
55
@RemkoPopma su biblioteca picocli se ve genial y gracias por hacerlo, de verdad. Pero considero lo que está haciendo aquí y en otras publicaciones (edite las respuestas aceptadas y promocione su biblioteca en la parte superior sin siquiera revelar que es una edición que no es del autor original de la publicación y es su lib) un horrible horrible abuso de sus poderes de moderación. Marcar esto a otras modificaciones.
Alexander Malakhov
312

Echa un vistazo al JCommander más reciente .

Yo lo creé. Estoy feliz de recibir preguntas o solicitudes de funciones.

Cedric Beust
fuente
77
Me alegra que te guste JCommander :-) No quería agregar demasiada semántica a la forma en que se tratan las banderas, por lo que solo necesitas agregar sinónimos en las anotaciones que utilizas: @Parameter (names = {"-h", "- -help "}) Pensé que era un compromiso razonable.
Cedric Beust
14
Gran herramienta Potente, flexible y no tiene que lidiar con los molestos analizadores de opciones tradicionales.
IanGilham
3
Sí, creo que habría escrito mi propio analizador de argumentos de línea de comandos exactamente de la misma manera que escribiste JCommander. Buen trabajo.
SRG
99
@CedricBeust, esta es una biblioteca brillante, muchas gracias. Dado que podemos definir nuestras propias clases Args que luego se pueden pasar sin ninguna dependencia de una clase de bibliotecas, lo hace extremadamente flexible.
Brett Ryan
2
sopla la competencia fuera del agua!
Marcus Junius Brutus
235

He estado tratando de mantener una lista de analizadores Java CLI .

léxico
fuente
77
@Ben Flynn jeje, hay algunas ruedas con formas bastante sorprendentes e interesantes. ¡Supongo que es una forma casi inofensiva de demostrar que hay muchas más formas de hacerlo!
lexicalscope
14
¡Noto que el autor de JOpt Simple mantiene una lista muy similar! Lo que necesitamos es texto para convertir estas listas en una tabla, enumerando características y puntos de interés, para que los usuarios pobres podamos tomar una decisión informada.
Tom Anderson
1
He creado Rop - github.com/ryenus/rop , que presenta una solución basada en anotaciones para declarar comandos y opciones a través de clases y campos simples, más o menos una forma declarativa de construir analizadores de línea de comandos. puede construir aplicaciones similares a Git (cmd único) o Maven (cmd múltiple).
ryenus
8
La mayoría de los proyectos enumerados son esencialmente abandonware. Después de revisar la lista, diría que los grandes bateadores, que se mantienen activamente y son populares, parecen commons-cli, jcommander, args4j, jopt-simple y picocli. Disculpas a los autores de cosas como argparse4j y cli-parser: tuve que hacer una clasificación algo arbitraria y elegir uno de los cinco primeros, claramente otros proyectos en la lista son populares y todavía están en desarrollo activo.
George Hawkins
2
Reto a alguien a que incluya la fecha de la última versión estable de cada analizador.
Trineo el
50

Es 2020, es hora de hacerlo mejor que Commons CLI ... :-)

¿Debería crear su propio analizador de línea de comandos Java o utilizar una biblioteca?

Es probable que muchas pequeñas aplicaciones similares a servicios utilicen su propio análisis de línea de comandos para evitar la dependencia externa adicional. picocli puede ser una alternativa interesante.

Picocli es una biblioteca y un marco modernos para crear aplicaciones de línea de comandos potentes, fáciles de usar y habilitadas para GraalVM con facilidad. Vive en 1 archivo fuente, por lo que las aplicaciones pueden incluirlo como fuente para evitar agregar una dependencia.

Admite colores, autocompletado, subcomandos y más. Escrito en Java, utilizable desde Groovy, Kotlin, Scala, etc.

Ayuda de uso mínimo con colores ANSI

caracteristicas:

  • Basado en anotaciones: declarativo , evita la duplicación y expresa la intención del programador
  • Conveniente: analice la entrada del usuario y ejecute su lógica de negocios con una línea de código
  • Escriba todo con firmeza : opciones de línea de comando y parámetros posicionales
  • POSIX agrupa las opciones cortas ( <command> -xvfInputFileasí como <command> -x -v -f InputFile)
  • Control de grano fino : un modelo de aridad que permite un número mínimo, máximo y variable de parámetros, por ejemplo "1..*","3..5"
  • Subcomandos (se pueden anidar a una profundidad arbitraria)
  • Rico en funciones: grupos de argumentos componibles, división de argumentos entre comillas, subcomandos repetibles y muchos más
  • Fácil de usar : el mensaje de ayuda de uso usa colores para contrastar elementos importantes como nombres de opciones del resto de la ayuda de uso para reducir la carga cognitiva en el usuario
  • Distribuya su aplicación como una imagen nativa de GraalVM
  • Funciona con Java 5 y superior
  • Documentación extensa y meticulosa

El mensaje de ayuda de uso es fácil de personalizar con anotaciones (sin programación). Por ejemplo:

Mensaje de ayuda de uso extendido( fuente )

No pude resistirme a agregar una captura de pantalla más para mostrar qué mensajes de ayuda de uso son posibles. La ayuda de uso es la cara de su aplicación, ¡así que sea creativo y diviértase!

demo picocli

Descargo de responsabilidad: creé picocli. Comentarios o preguntas muy bienvenidos.

Remko Popma
fuente
55
¡Genio puro! Es una pena que esta respuesta esté enterrada en el fondo. La CLI de Apache Commons es detallada, con errores y no se ha actualizado en mucho tiempo. Y no quiero usar el analizador CLI de Google porque no quiero anuncios dirigidos basados ​​en mi historial de uso de argumentos de línea de comando. Pero de todos modos se ve un poco más detallado que picocli.
Pete
2
Segundo @Pete aquí ... Revisé la lista anterior, que fue una pérdida de tiempo completa con esto enterrado en la parte inferior. Esta debería ser la mejor respuesta por una milla. ¡Gran trabajo! Mis requisitos no podían ser cubiertos por la CLI de apache o la mayoría de estos otros analizadores. Eran un desafío incluso para picocli, pero fue capaz de darme lo más parecido a la sintaxis / comportamiento que quería y fue lo suficientemente flexible como para piratear lo que realmente necesitaba. Como beneficio adicional, se ve muy bien gracias a las cosas de ANSI.
Shai Almog
@ShaiAlmog La respuesta más votada tiene 10 años y está desactualizada. Estoy de acuerdo en que recomendar Commons CLI en 2019 es engañoso en mi humilde opinión. Considere reescribir la respuesta principal para que esté más actualizada.
Remko Popma
Veo que ya lo intentaste, no creo que eso funcione para mí tampoco ... Si hubieras elegido un nombre como 1Picoli, podríamos haber ordenado alfabéticamente la tercera respuesta ;-)
Shai Almog
Creo que la razón por la que mi cambio fue revertido es que no revelé mi afiliación (que soy el autor). Otras personas no deberían tener ese problema.
Remko Popma
23

He usado JOpt y lo he encontrado bastante útil: http://jopt-simple.sourceforge.net/

La página principal también proporciona una lista de aproximadamente 8 bibliotecas alternativas, échales un vistazo y elige la que más se adapte a tus necesidades.

GaryF
fuente
21

Alguien me señaló args4j últimamente, que está basado en anotaciones. ¡Me gusta mucho!

André
fuente
1
+1 para Args4J! Extremadamente amigable con los humanos, flexible y comprensible. Creo que debería ser la biblioteca estándar para construir aplicaciones Java CLI.
Zearin
Es genial que pueda manejar impresiones de uso desordenadas (ordenadas por orden de campo), que JCommander no puede, y es más flexible.
Daniel Hári
@ DanielHári Solo para información, esta funcionalidad se agregó en JCommander (en algún momento a fines de febrero de 2017).
Nathan
9

Esta es la biblioteca de análisis de línea de comandos de Google de código abierto como parte del proyecto Bazel. Personalmente, creo que es el mejor y mucho más fácil que la CLI de Apache.

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

Instalación

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>

Uso

Cree una clase que amplíe OptionsBasey defina sus @Option(s).

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;

}

Analiza los argumentos y úsalos.

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

Pablo
fuente
Hola Pablo. Cuando leo su respuesta o la documentación de su proyecto, no tengo idea de qué tipo de línea de comando puede manejar. Por ejemplo, puede proporcionar algo como myexecutable -c file.json -d 42 --outdir ./out. Y no veo cómo se definen las opciones de descripción corta / larga ... Saludos
olibre
8

Eche un vistazo al proyecto de la CLI de Commons , muchas cosas buenas allí.

Marc Novakowski
fuente
8

Yeap

Creo que estás buscando algo como esto: http://commons.apache.org/cli

La biblioteca CLI de Apache Commons proporciona una API para procesar interfaces de línea de comandos.

OscarRyz
fuente
7

Sé que la mayoría de la gente aquí encontrará 10 millones de razones por las que no les gusta mi camino, pero no importa. Me gusta mantener las cosas simples, así que solo separo la clave del valor usando un '=' y las almaceno en un HashMap como este:

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

Siempre puede mantener una lista con los argumentos que espera, para ayudar al usuario en caso de que haya olvidado un argumento o haya utilizado uno incorrecto ... Sin embargo, si desea demasiadas funciones, esta solución no es para usted de todos modos.

John Koumarelas
fuente
7

Tal vez estos

mepcotterell
fuente
5

Escribí otro: http://argparse4j.sourceforge.net/

Argparse4j es una biblioteca de analizador de argumentos de línea de comandos para Java, basada en el argumento de Python.

Tatsuhiro Tsujikawa
fuente
¡Bienvenido a Stack Overflow! Gracias por publicar tu respuesta! Asegúrese de leer atentamente las preguntas frecuentes sobre autopromoción.
Andrew Barber
4

Si ya está utilizando Spring Boot, el análisis de argumentos sale de la caja.

Si desea ejecutar algo después del inicio, implemente la ApplicationRunnerinterfaz:

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

Su runmétodo se invocará después de que el contexto se haya iniciado correctamente.

Si necesita acceder a los argumentos antes de activar el contexto de su aplicación, simplemente puede analizar los argumentos de la aplicación manualmente:

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

}

Y finalmente, si necesita acceso a sus argumentos en un bean, simplemente inyecte ApplicationArguments:

@Component
public class MyBean {

   @Autowired
   private ApplicationArguments arguments;

   // ...
}
Stefan Haberl
fuente
Esto es asombroso :).
John Humphreys - w00te
3

Argparse4j es el mejor que he encontrado. Imita la biblioteca argparse de Python, que es muy conveniente y potente.

Trismegistos
fuente
2

Si desea algo liviano (tamaño de jarra ~ 20 kb) y fácil de usar, puede probar el analizador de argumentos . Se puede usar en la mayoría de los casos de uso, admite la especificación de matrices en el argumento y no depende de ninguna otra biblioteca. Funciona para Java 1.5 o superior. El siguiente extracto muestra un ejemplo sobre cómo usarlo:

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

Más ejemplos se pueden encontrar aquí

Himanshu Shekhar
fuente
1
Link está muerto. ¿Mataste tu proyecto? :-(
beldaz
2

No recomendaría usar Apache Common CLI biblioteca, ya que no es segura para subprocesos.

Utiliza clases con estado con variables estáticas y métodos para hacer trabajo interno (por ejemplo OptionBuilder) y solo debe usarse en situaciones de un solo subproceso fuertemente controladas.

Jakub
fuente
18
Es bueno tener en cuenta que la biblioteca CLI no es segura para subprocesos. Sin embargo, supongo que el análisis de la línea de comandos generalmente se realiza en un solo subproceso durante el inicio de la aplicación, y luego, dependiendo de los parámetros, se pueden iniciar otros subprocesos.
Alexey Ivanov
0

Como uno de los comentarios mencionados anteriormente ( https://github.com/pcj/google-options ) sería una buena opción para comenzar.

Una cosa que quiero agregar es:

1) Si se encuentra con algún error de reflexión del analizador, intente utilizar una versión más reciente de la guayaba. en mi caso:

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) Al ejecutar la línea de comando:

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

3) Cuando necesite la ayuda de uso, simplemente escriba:

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

Para los usuarios de Spring, debemos mencionar también https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/env/SimpleCommandLinePropertySource.html y su hermano gemelo https: //docs.spring .io / spring / docs / current / javadoc-api / org / springframework / core / env / JOptCommandLinePropertySource.html (implementación JOpt de la misma funcionalidad). La ventaja en Spring es que puede vincular directamente los argumentos de la línea de comandos a los atributos, aquí hay un ejemplo https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/env/ CommandLinePropertySource.html

Pierluigi Vernetto
fuente