Как мне разобрать аргументы командной строки в Java?

586

Что такое хороший способ анализа аргументов командной строки в Java?

Линделоф
источник
4
См. Args4j и подробный пример того, как его использовать: martin-thoma.com/how-to-parse-command-line-arguments-in-java
Мартин Тома
Похоже, я довольно опоздал на эту вечеринку, но я написал обработчик аргументов командной строки для Java и поместил его в GitHub: MainArgsHandler . Что касается закрытия потока, я думаю, что это очень полезный поток, но, возможно, его следует перенести на сайт программистов Stack Exchange для общего обсуждения программирования.
Великолепно
@RedGlyph - похоже, SO / SE нужно упростить свои правила. Этот вопрос должен быть: How to parse java command line arguments?. Но никто действительно не хочет писать код для этого, а использовать инструмент. Но поиск инструментов и подобных
вещей
6
Проголосовал за открытие. @AlikElzin: Действительно, им нужно пересмотреть процесс модерирования. Я подозреваю, что есть значок для закрытия очень многих вопросов, и это заманивает желающих быть модераторами слишком усердными.
RedGlyph
8
Этот вопрос является приманкой для плохих / однострочных ответов и рекомендаций инструмента. Он должен оставаться закрытым.
JAL

Ответы:

405

Проверьте это:

Или сверните свое собственное:


Например, вот как вы используете commons-cliдля анализа 2 строковых аргументов:

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

    }

}

использование из командной строки:

$> 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
Винко Врсалович
источник
40
Обратите внимание, что в отличие от многих других библиотек Apache, Apache CLI не имеет зависимостей.
Владимир Дюжев
9
Единственным недостатком многих проектов Apache-Commons является то, что они получают все меньше и меньше коммитов и в конечном итоге оказываются устаревшими.
Бретт Райан
4
Вот страница «Сценарии использования» для проекта Apache CLI, в которой подробно рассказывается, как быстро начать его использовать: commons.apache.org/cli/usage.html
Брэд Паркс,
Я не думаю, что есть такой же, как Args4J / JCommander, кроме случаев, когда вы определяете интерфейс и комментируете методы? Я никогда не был в состоянии полюбить классы, которые "жутко инициализируют" частные поля ...
Trejkaz
5
@RemkoPopma, ваша библиотека picocli выглядит просто великолепно, и спасибо вам за это, правда. Но я считаю, что вы делаете здесь и в других постах (редактируйте принятые ответы и рекламируйте свою библиотеку в верхней части страницы, даже не раскрывая, что это редактирование не от оригинального автора поста и это ваша библиотека), ужасно ужасное злоупотребление вашими полномочиями модерирования. Отметить это для других модов.
Александр Малахов
312

Взгляните на более свежий JCommander .

Я создал это. Я рад получить вопросы или пожелания.

Седрик Беуст
источник
7
Рад, что вам нравится JCommander :-) Я не хотел добавлять слишком много семантики к тому, как обрабатываются флаги, поэтому вам просто нужно добавить синонимы в используемых вами аннотациях: @Parameter (names = {"-h", "- -помощь "}) Я думал, что это разумный компромисс.
Седрик Бест
14
Отличный инструмент. Мощный, гибкий, и вам не нужно иметь дело с раздражающими, традиционными парсерами опций.
Ян Гилхэм
3
Да, я думаю, что написал бы мой собственный анализатор аргументов командной строки точно так же, как вы написали JCommander. Отличная работа.
SRG
9
@CedricBeust, это замечательная библиотека, я вам очень благодарен. Поскольку мы можем определять наши собственные классы Args, которые затем можно передавать без какой-либо зависимости от класса библиотек, это делает его чрезвычайно гибким.
Бретт Райан
2
уносит соревнование из воды!
Маркус Юний Брут
235

Я пытался поддерживать список парсеров Java CLI .

lexicalscope
источник
7
@ Бен Флинн хе-хе, там есть несколько довольно удивительных и интересных колес в форме. Я думаю, это в основном безвредный способ показать, что есть гораздо больше, чем один способ сделать это!
lexicalscope
14
Отмечу, что автор JOpt Simple поддерживает очень похожий список! Нам нужен текст, чтобы превратить эти списки в таблицу со списком функций и достопримечательностей, чтобы мы, бедные пользователи, могли сделать осознанный выбор.
Том Андерсон
1
Я создал Rop - github.com/ryenus/rop , в котором реализовано решение на основе аннотаций, в котором вы объявляете команды и параметры через простые классы и поля, в значительной степени декларативный способ создания анализаторов командной строки. он может создавать приложения типа Git (single-cmd) или Maven (multi-cmd).
ryenus
8
Большинство перечисленных проектов по сути являются заброшенными. Пройдя по списку, я бы сказал, что крупные нападающие, которые активно поддерживаются и популярны, кажутся commons-cli, jcommander, args4j, jopt-simple и picocli. Извиняюсь перед авторами таких вещей, как argparse4j и cli-parser - мне пришлось сделать несколько произвольное ранжирование, и я выбрал пятерку, очевидно, что другие проекты в списке популярны и все еще находятся в активной разработке.
Джордж Хокинс
2
Я призываю кого-то включить дату последнего стабильного выпуска каждого парсера.
Санки
50

Это 2020 год, время, чтобы сделать лучше, чем CLI Commons ... :-)

Должны ли вы создать свой собственный анализатор командной строки Java или использовать библиотеку?

Многие небольшие подобные приложения, вероятно, запускают собственный синтаксический анализ командной строки, чтобы избежать дополнительной внешней зависимости. Picocli может быть интересной альтернативой.

Picocli - это современная библиотека и инфраструктура для удобного создания мощных, удобных для пользователя приложений с поддержкой GraalVM. Он находится в 1 исходном файле, поэтому приложения могут включать его в качестве источника, чтобы избежать добавления зависимости.

Он поддерживает цвета, автозаполнение, подкоманды и многое другое. Написано на Java, доступно из Groovy, Kotlin, Scala и т. Д.

Справка по минимальному использованию цветов ANSI

Особенности:

  • Основанный на аннотации: декларативный , избегает дублирования и выражает намерение программиста
  • Удобно: анализировать пользовательский ввод и запускать бизнес-логику с помощью одной строки кода
  • Все строго набрано - параметры командной строки, а также позиционные параметры
  • POSIX кластерные короткие опции ( <command> -xvfInputFileа также <command> -x -v -f InputFile)
  • Детальное управление : модель арности, которая допускает минимальное, максимальное и переменное количество параметров, например "1..*","3..5"
  • Подкоманды (могут быть вложены на произвольную глубину)
  • Многофункциональный : составные группы аргументов, разбиение аргументов в кавычках, повторяемые подкоманды и многое другое
  • Удобный для пользователя : в справочном сообщении об использовании используются цвета для контрастирования важных элементов, таких как имена опций, от остальной части использования, которые помогают снизить когнитивную нагрузку на пользователя
  • Распространите свое приложение как собственный образ GraalVM
  • Работает с Java 5 и выше
  • Обширная и дотошная документация

Справочное сообщение об использовании легко настроить с помощью аннотаций (без программирования). Например:

Расширенное справочное сообщение об использовании( источник )

Я не мог удержаться от добавления еще одного скриншота, чтобы показать, какие сообщения об использовании возможны. Справка по использованию - это лицо вашего приложения, так что будьте изобретательны и получайте удовольствие!

пикокли демо

Отказ от ответственности: я создал picocli. Отзывы или вопросы очень приветствуются.

Ремко Попма
источник
5
Чистый гений! Обидно, этот ответ похоронен внизу. Apache Commons CLI является многословным, содержит ошибки и давно не обновлялся. И я не хочу использовать синтаксический анализатор CLI от Google, потому что я не хочу целевых рекламных объявлений, основанных на моей истории использования аргументов командной строки. Но все равно выглядит немного более многословно, чем пикокли.
Пит
2
Я второй @ Пит здесь ... Я прошел список выше, который был пустой тратой времени с этим, похороненным внизу. Это должен быть главный ответ на милю. Отличная работа! Мои требования не могут быть покрыты Apache CLI или большинством других парсеров. Они бросали вызов даже для picocli, но он был в состоянии дать мне наиболее близкую вещь к синтаксису / поведению, которое я хотел, и был достаточно гибок, чтобы взломать то, что мне действительно нужно. В качестве бонуса это здорово смотрится благодаря материалу ANSI.
Shai
@ShaiAlmog Ответ с самым высоким рейтингом - 10 лет и он устарел. Я согласен, что рекомендация CLI Commons в 2019 году вводит в заблуждение ИМХО. Пожалуйста, подумайте над тем, чтобы переписать лучший ответ, чтобы сделать его более актуальным.
Ремко
Я вижу, вы уже пробовали это, я не думаю, что это будет работать и для меня ... Если бы вы выбрали имя, такое как 1Picoli, мы могли бы отсортировать третий ответ по алфавиту ;-)
Shai
Я думаю, что причина моего изменения была в том, что я не раскрыл свою принадлежность (что я автор). У других людей не должно быть этой проблемы.
Ремко
23

Я использовал JOpt и нашел его очень удобным: http://jopt-simple.sourceforge.net/

На главной странице также представлен список из 8 альтернативных библиотек, посмотрите их и выберите ту, которая больше всего соответствует вашим потребностям.

GaryF
источник
21

Кто-то недавно указал мне на args4j, основанный на аннотациях. Мне это и вправду нравится!

Андре
источник
1
+1 для Args4J! Чрезвычайно дружелюбный, гибкий и понятный. Я думаю, что это должна быть стандартная библиотека для создания приложений Java CLI.
Зерин
Замечательно, что он может обрабатывать неупорядоченные (отсортированные по полевому порядку) печати, что не может JCommander, и он более гибкий.
Даниэль Хари
@ DanielHári Только для информации, эта функциональность была добавлена ​​в JCommander (где-то в конце февраля 2017 года).
Натан
9

Это библиотека синтаксического анализа командной строки Google, открытая как часть проекта Bazel. Лично я считаю, что он лучший и намного проще, чем Apache CLI.

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

Установка

Базэл

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

специалист

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

Применение

Создайте класс, который расширяет OptionsBaseи определяет ваши @Option(и).

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;

}

Разбери аргументы и используй их.

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

Павел
источник
Привет, Пол. Когда я читаю ваш ответ или документацию вашего проекта, я не имею ни малейшего представления, с какой командной строкой он может работать. Например, вы можете предоставить что-то вроде myexecutable -c file.json -d 42 --outdir ./out. И я не вижу, как вы определяете короткие / длинные / описания параметров ... Ура
olibre
8

Взгляните на проект Commons CLI , там много хорошего.

Марк Новаковский
источник
8

Yeap.

Я думаю, что вы ищете что-то вроде этого: http://commons.apache.org/cli

Библиотека CLI Apache Commons предоставляет API для обработки интерфейсов командной строки.

OscarRyz
источник
7

Я знаю, что большинство людей здесь найдут 10 миллионов причин, почему им не нравится мой путь, но не берите в голову. Мне нравится делать вещи простыми, поэтому я просто отделяю ключ от значения, используя '=', и сохраняю их в HashMap следующим образом:

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

Вы всегда можете вести список с ожидаемыми аргументами, чтобы помочь пользователю в случае, если он забыл аргумент или использовал неправильный ... Однако, если вам нужно слишком много функций, это решение в любом случае не для вас.

Джон Кумарелас
источник
7

Может быть эти

mepcotterell
источник
6

Вы могли бы найти эту мета-статью несчастья интересной как отправную точку:

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

Алекс Миллер
источник
2
Этот парень довольно бесполезен: «Commons CLI. По-видимому, самый старый из предложенных здесь вариантов, и он не получает большого уважения от комментаторов, поэтому я не очень внимательно смотрю на это…», но все равно спасибо за ссылку.
Джеймс МакМэхон
5

Я написал еще один: http://argparse4j.sourceforge.net/

Argparse4j - это библиотека анализатора аргументов командной строки для Java, основанная на argparse Python.

Тацухиро Цудзикава
источник
Добро пожаловать в переполнение стека! Спасибо за публикацию вашего ответа! Пожалуйста, внимательно прочитайте FAQ по саморекламе .
Эндрю Барбер
4

Если вы уже используете Spring Boot, разбор аргументов происходит из коробки.

Если вы хотите запустить что-то после запуска, реализуйте ApplicationRunnerинтерфейс:

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

Ваш runметод будет вызван после успешного запуска контекста.

Если вам нужен доступ к аргументам до запуска контекста приложения, вы можете просто проанализировать аргументы приложения вручную:

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

}

И наконец, если вам нужен доступ к вашим аргументам в бине, просто введите ApplicationArguments:

@Component
public class MyBean {

   @Autowired
   private ApplicationArguments arguments;

   // ...
}
Стефан Хаберл
источник
Это круто :).
Джон Хамфрис -
3

Argparse4j - лучшее, что я нашел. Он имитирует argparse-библиотеку Python, которая очень удобна и мощна.

Трисмегиста
источник
2

Если вы хотите что-то более легкое (размер банки ~ 20 кб) и простое в использовании, вы можете попробовать аргумент-парсер . Он может использоваться в большинстве случаев, поддерживает указание массивов в аргументе и не зависит от какой-либо другой библиотеки. Это работает для Java 1.5 или выше. Ниже приведен пример того, как его использовать:

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

Больше примеров можно найти здесь

Химаншу Шехар
источник
1
Ссылка мертва. Ты убил свой проект? :-(
Белдаз
2

Я бы не рекомендовал использовать Apache Common CLI библиотеку, так как она не является поточно-безопасной.

Он использует классы с состоянием со статическими переменными и методами для выполнения внутренней работы (например OptionBuilder) и должен использоваться только в однопоточных строго контролируемых ситуациях.

Якуб
источник
18
Следует помнить, что библиотека CLI не является поточно-ориентированной. Однако я бы предположил, что синтаксический анализ командной строки обычно выполняется в одном потоке во время запуска приложения, а затем, в зависимости от параметров, могут запускаться другие потоки.
Алексей Иванов
0

Как один из упомянутых ранее комментариев ( https://github.com/pcj/google-options ), было бы хорошим выбором для начала.

Одна вещь, которую я хочу добавить:

1) Если вы столкнулись с ошибкой отражения парсера, попробуйте использовать более новую версию гуавы. в моем случае:

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) При запуске командной строки:

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

3) Если вам нужна помощь в использовании, просто введите:

bazel run path/to/your:project -- --help
Stevens
источник
-1

Для пользователей Spring следует также упомянуть https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/env/SimpleCommandLinePropertySource.html и его брата-близнеца https: //docs.spring .io / spring / docs / current / javadoc-api / org / springframework / core / env / JOptCommandLinePropertySource.html (реализация JOpt с той же функциональностью). Преимущество в Spring заключается в том, что вы можете напрямую связать аргументы командной строки с атрибутами, здесь есть пример https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/env/ CommandLinePropertySource.html

Пьерлуиджи Вернетто
источник