Як я можу аналізувати аргументи командного рядка на Java?


586

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


4
Дивіться args4j та докладний приклад, як його використовувати: martin-thoma.com/how-to-parse-command-line-arguments-in-java
Martin Thoma

Схоже, я досить запізнююся на цю партію, але я написав обробник аргументів командного рядка для Java і поставив її на GitHub: MainArgsHandler . Щодо потоку, який закривається, я вважаю, що це дуже корисна тема, але вона, можливо, має бути перенесена на сайт програмістів Stack Exchange для обговорення загального програмування.
Bobulous

@RedGlyph - Схоже, що SO / SE потрібно спростити свої правила. Це питання має бути: How to parse java command line arguments?. Але ніхто не хоче писати код для цього, а скоріше використовувати інструмент. Але пошук інструментів і подібних не конструктивний :(
AlikElzin-kilaka

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
Ось сторінка "Сценарії використання" для проекту CLI Apache, в якій детально описано, як швидко розпочати його використання: commons.apache.org/cli/usage.html
Бред Паркс

Я не думаю, що існує такий, як Args4J / JCommander, за винятком випадків, коли ви визначаєте інтерфейс та коментуєте методи? Мені ніколи не вдалося полюбити заняття, які "моторошно ініціалізують" приватні поля ...
Trejkaz

5
@RemkoPopma, ваша бібліотека пікоклі виглядає просто чудово, і дякую вам за це. Але я вважаю, що ви робите тут і в інших публікаціях (редагуйте прийняті відповіді та просувайте свою бібліотеку вгорі, навіть не розголошуючи, що це редакція не від оригіналу автора публікації, а це ваша власна сила) жахливим жахливим зловживанням вашими повноваженнями на модерацію. Позначаючи це іншими модами.
Олександр Малахов

312

Погляньте на новіший JCommander .

Я його створив. Я радий отримувати запитання чи запити щодо функцій.


7
Рада, що вам подобається JCommander :-) Я не хотів додавати занадто багато семантичного в поводження з прапорами, тому вам просто потрібно додати синоніми до анотацій, які ви використовуєте: @Parameter (names = {"-h", "- -допомога "}) Я вважав, що це розумний компроміс.
Седрік Беуст

14
Чудовий інструмент. Потужний, гнучкий, і вам не доведеться мати справу з дратівливими, традиційними аналізаторами варіантів.
IanGilham

3
Так, я думаю, я написав би свій власний аргумент командного рядка аналізатором точно так само, як ви написали JCommander. Чудова робота.
SRG

9
@CedricBeust, це геніальна бібліотека, дуже дякую. Оскільки ми можемо визначити власні класи Args, які потім можна пройти без будь-якої залежності від класу бібліотек, це робить його надзвичайно гнучким.
Бретт Райан

2
видуває конкуренцію з води!
Маркус Юній Брут

235

7
@Ben Flynn hehe, є кілька досить дивовижних і цікавих формних коліс. Я думаю, що це здебільшого нешкідливий спосіб показати, що існує багато способів зробити це!
лексикаскоп

14
Зауважу, автор JOpt Simple веде дуже подібний список! Нам потрібен текст - це перетворити ці списки в таблицю з переліком особливостей та цікавих точок, щоб ми, бідні користувачі, могли зробити усвідомлений вибір.
Том Андерсон

1
Я створив Rop - github.com/ryenus/rop , який пропонує рішення на основі анотацій, що ви оголошуєте команди та параметри за допомогою простих класів та полів, що є декларативним способом побудови парсерів командних рядків. він може створювати або Git (одиночний cmd), або Maven (мульти cmd), як додатки.
ryenus

8
Більшість перерахованих проектів, по суті, є занедбаними. Переглянувши список, я б сказав, що великі нападники, які активно підтримуються та популярні, здаються commons-cli, jcommander, args4j, jopt-simple та picocli. Вибачте перед авторами таких речей, як argparse4j та cli-parser - мені довелося скласти дещо довільний рейтинг і обрали першу п’ятірку. Очевидно, інші проекти в списку популярні, але ще й зараз активно розвиваються.
Джордж Хокінс

2
Я закликаю когось включити дату останнього стабільного випуску кожного аналізатора.
Санки

50

Настав 2020 рік, час зробити краще, ніж Commons CLI ... :-)

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

Багато малих програм, схожих на утиліту, ймовірно, розгортають власний аналіз командного рядка, щоб уникнути додаткової зовнішньої залежності. пікоклі може бути цікавою альтернативою.

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

Він підтримує кольори, автозавершення, підкоманди тощо. Написано на Java, можна використовувати з Groovy, Kotlin, Scala тощо.

Допомога щодо мінімального використання кольорів ANSI

Особливості:

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

Повідомлення довідки про використання легко налаштувати за допомогою приміток (без програмування). Наприклад:

Поширене довідкове повідомлення про використання( джерело )

Я не втримався додати ще один знімок екрана, щоб показати, які можливі повідомлення щодо використання можливі. Допомога щодо використання - це обличчя вашої заявки, тому будьте креативними і веселіться!

демонстрація пікоклі

Відмова: Я створив пікоклі. Відгуки або питання дуже вітаються.


5
Чистий геній! Соромно, що ця відповідь похована внизу. CLI Apache Commons є багатослівним, баггі, і його не оновлювали давно. І я не хочу використовувати аналізатор CLI Google, тому що не хочу націлювати рекламу на основі історії використання аргументів командного рядка. Але це все одно виглядає трохи більш багатослівно, ніж пікоклі.
Піт

2
Я другий @Pete тут ... Я переглянув список, над яким було повна трата часу з цим похованим внизу. Це має бути головна відповідь за милю. Чудова робота! Мої вимоги не могли бути покриті апач CLI або більшості цих інших аналізаторів. Вони були складними навіть для пікоклі, але він зміг надати мені найближчу річ до синтаксису / поведінки, якого я хотів, і був досить гнучким, щоб зламати те, що мені справді потрібно. Як бонус, це чудово виглядає завдяки матеріалам ANSI.
Шай Алмог

@ShaiAlmog Відповідь, що голосує на вершині голосів, 10 років і застаріла. Я погоджуюся, що рекомендувати Commons CLI у 2019 році вводити в оману IMHO. Будь ласка, спробуйте переписати верхню відповідь, щоб зробити її більш актуальною.
Ремко Попма

Я бачу, ви вже пробували це, я не думаю, що для мене це теж спрацює ... Якби ви вибрали таке ім'я, як 1Picoli, ми могли б сортувати 3-ту відповідь за алфавітом ;-)
Шай Алмог

Я думаю, що причиною моєї зміни було відмінено те, що я не розголосив свою приналежність (що я автор). Інші люди не повинні мати цього питання.
Ремко Попма

23

Я використовував JOpt і вважав це досить зручним: http://jopt-simple.sourceforge.net/

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


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",
)

Градле

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. І я не бачу, як ви визначаєте параметри короткого / довгого / опису ... Ура
олибре



7

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

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

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


7

Можливо, ці

  • Набір параметрів командного рядка командного рядка JArgs для Java - цей крихітний проект забезпечує зручний, компактний, попередньо упакований та всебічно задокументований набір аналізаторів параметрів командного рядка для використання програмістами Java. Спочатку надається аналіз, сумісний із "getopt" у стилі GNU.

  • ritopt, The Ultimate Options Parser для Java - Хоча запропоновано декілька стандартів параметрів командного рядка, ritopt дотримується конвенцій, прописаних у пакеті opt.


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;

   // ...
}

Це круто :).
Джон Хамфріс - w00te

3

Argparse4j - найкраще, що я знайшов. Це імітує арбітражну бібліотеку 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
Посилання мертва. Ви вбили проект? :-(
beldaz

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

-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 тієї самої функціональності). Перевага навесні полягає в тому, що ви можете безпосередньо прив’язувати аргументи командного рядка до атрибутів, тут є приклад https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/core/env/ CommandLinePropertySource.html

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.