Java에서 명령 줄 인수를 어떻게 구문 분석합니까?


586

Java에서 명령 행 인수를 구문 분석하는 좋은 방법은 무엇입니까?


4
args4j 및 사용 방법에 대한 자세한 예를 참조하십시오. martin-thoma.com/how-to-parse-command-line-arguments-in-java
Martin Thoma

이 파티에 꽤 늦었 던 것 같지만 Java 용 명령 줄 인수 처리기를 작성하여 GitHub에 넣었습니다 : MainArgsHandler . 스레드가 닫히는 것은 이것이 매우 유용한 스레드라고 생각하지만 일반적인 프로그래밍 토론을 위해 Stack Exchange Programmers 사이트로 마이그레이션해야 할 수도 있습니다.
Bobulous

@RedGlyph-SO / SE가 규칙을 단순화해야하는 것처럼 보입니다. 문제는 다음과 같아야합니다 How to parse java command line arguments?. 그러나 실제로이 작업을 수행하기 위해 코드를 작성하는 대신 도구를 사용하려는 사람은 없습니다. 그러나 도구와
유사한

6
재개 투표. @AlikElzin : 실제로, 그들은 그들의 중재 과정을 검토해야합니다. 너무 많은 질문을 마무리 짓는 배지가 있다고 생각하며, 조정자가되기를 원하는 것은 너무 열심입니다.
RedGlyph

8
이 질문은 잘못된 / 한 줄 답변 및 도구 권장 사항에 대한 허니팟입니다. 닫혀 있어야합니다.
JAL

답변:


405

이것들을 확인하십시오 :

또는 자신의 롤 :


예를 들어 다음은 commons-cli2 개의 문자열 인수를 구문 분석 하는 방법입니다 .

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
많은 아파치-커먼즈 프로젝트의 단점 중 하나는 커밋이 점점 줄어들고 결국 더 이상 사용되지 않는다는 것입니다.
Brett Ryan

4
다음은 신속하게 사용 방법에 대해 자세히 아파치 CLI 프로젝트의 "사용 시나리오"페이지의 commons.apache.org/cli/usage.html
브래드 공원

인터페이스를 정의하고 메소드에 주석을 달는 것을 제외하고 Args4J / JCommander와 정확히 같은 것이 있다고 생각하지 않습니다. 개인 필드를 "초기화"하는 클래스를
좋아할 수 없었습니다

5
@RemkoPopma 당신의 picocli 라이브러리는 훌륭해 보이고 정말 감사합니다. 그러나 나는 당신이 여기와 다른 게시물에서하고있는 일을 고려합니다 (허용 된 답변을 편집하고 라이브러리의 게시물을 게시하지 않고 편집 한 것을 게시하지 않고 라이브러리를 홍보하지 않아도됩니다). 이것을 다른 개조에 표시합니다.
Alexander Malakhov

312

최신 JCommander를 살펴보십시오 .

나는 그것을 만들었다. 질문이나 기능 요청을 받겠습니다.


7
JCommander를 좋아해서 기쁘다 :-) 플래그가 처리되는 방식에 너무 많은 의미를 추가하고 싶지 않았으므로 사용하는 주석에 동의어를 추가하면됩니다. @Parameter (names = { "-h", "- -help "}) 합리적인 타협이라고 생각했습니다.
Cedric Beust

14
훌륭한 도구입니다. 강력하고 유연하며 성가신 전통적인 옵션 파서를 다룰 필요가 없습니다.
IanGilham

3
예, JCommander를 작성한 것과 동일한 방식으로 내 명령 줄 인수 파서를 작성했을 것입니다. 훌륭한 일.
SRG

9
@CedricBeust, 이것은 훌륭한 도서관입니다. 대단히 감사합니다. 라이브러리 클래스에 의존하지 않고 전달할 수있는 자체 Args 클래스를 정의 할 수 있으므로 매우 유연합니다.
Brett Ryan

2
물 밖으로 경쟁을 날려 버립니다!
마커스 Junius Brutus

235

7
@Ben Flynn hehe, 거기에는 꽤 놀랍고 흥미로운 모양의 바퀴가 있습니다. 나는 그것을 할 수있는 여러 가지 방법이 많이 있음을 보여주는 가장 무해한 방법이라고 생각합니다!
lexicalscope

14
JOpt Simple의 저자는 매우 비슷한 목록을 유지합니다! 텍스트가 필요한 것은 이러한 목록을 표로 바꾸어 기능과 관심 지점을 나열하는 것이므로 가난한 사용자는 정보에 입각 한 선택을 할 수 있습니다.
Tom Anderson

1
나는 구축했습니다 (Rop)은 - github.com/ryenus/rop , 당신은 일반 클래스와 필드를 통해 명령과 옵션을 선언하는 것이 주석 기반 솔루션, 빌드 명령 줄 파서에 꽤 많이 선언적 방법을 제공합니다. Git (single-cmd) 또는 Maven (multi-cmd) 같은 앱을 빌드 할 수 있습니다.
Ryenus

8
나열된 대부분의 프로젝트는 기본적으로 포기됩니다. 목록을 살펴본 후 적극적으로 유지 관리되고 인기가 큰 큰 타자들은 commons-cli, jcommander, args4j, jopt-simple 및 picocli로 보입니다. argparse4j 및 cli-parser와 같은 저자의 사과-나는 다소 임의의 순위를 지정해야했으며 목록에서 다른 5 가지 프로젝트를 선택했습니다. 명확하고 다른 프로젝트도 여전히 활발하게 개발 중입니다.
George Hawkins

2
나는 누군가에게 각 파서의 마지막 안정 릴리스 날짜를 포함 시키도록 요청합니다.
썰매

50

그것은 Commons CLI보다 더 나은 시간을 2020입니다 ... :-)

자체 Java 명령 행 구문 분석기를 빌드하거나 라이브러리를 사용해야합니까?

많은 작은 유틸리티 유사 응용 프로그램은 추가 외부 종속성을 피하기 위해 자체 명령 행 구문 분석을 롤링 할 수 있습니다. picocli 는 흥미로운 대안이 될 수 있습니다.

Picocli는 강력하고 사용자 친화적 인 GraalVM 지원 명령 줄 앱을 쉽게 구축 할 수있는 최신 라이브러리 및 프레임 워크입니다. 하나의 소스 파일에 있으므로 앱이 종속성을 추가하지 않도록 소스로 포함시킬 수 있습니다.

색상, 자동 완성, 부속 명령 등을 지원합니다. Groovy, Kotlin, Scala 등에서 사용 가능한 Java로 작성

ANSI 색상에 대한 최소한의 사용 도움말

풍모:

  • 주석 기반 : 선언적 , 중복 방지 및 프로그래머 의도 표현
  • 편리 성 : 사용자 입력을 구문 분석하고 한 줄의 코드로 비즈니스 로직을 실행
  • 강력한 형식의 모든 것을 - 명령 줄 옵션뿐만 아니라 위치 매개 변수
  • POSIX 클러스터 된 짧은 옵션 ( <command> -xvfInputFile<command> -x -v -f InputFile)
  • 세밀하게 제어 : 최소, 최대 및 매개 변수의 개수를 허용하는 인수에 대응 모델, 예를 들면 "1..*","3..5"
  • 부속 명령 (임의의 깊이에 내포 될 수 있음)
  • 풍부한 기능 : 구성 가능한 arg 그룹, 인용 된 arg 분할, 반복 가능한 하위 명령 등
  • 사용자 친화적 : 사용 도움말 메시지는 색상을 사용하여 나머지 사용 도움말의 옵션 이름과 같은 중요한 요소를 대조 하여 사용자 의인지 부하줄입니다.
  • 앱을 GraalVM 기본 이미지 로 배포
  • 작동 자바 5 이상
  • 광범위하고 세심한 문서

사용법 도움말 메시지는 프로그래밍없이 주석으로 쉽게 사용자 정의 할 수 있습니다. 예를 들면 다음과 같습니다.

확장 된 사용법 도움말 메시지( 소스 )

사용 도움말 메시지가 표시되는 스크린 샷을 하나 더 추가하는 것에 저항 할 수 없었습니다. 사용 도움말은 응용 프로그램의 얼굴이므로 창의적이고 재미있게 보내십시오!

피코 클리 데모

면책 조항 : 나는 picocli를 만들었습니다. 의견이나 질문은 매우 환영합니다.


5
순수한 천재! 이 답변이 바닥에 묻힌 것은 부끄러운 일입니다. Apache Commons CLI는 장황하고 버그가 많으며 오랫동안 업데이트되지 않았습니다. 명령 줄 인수 사용 내역을 기반으로 타겟팅 된 광고를 원하지 않기 때문에 Google의 CLI 파서를 사용하고 싶지 않습니다. 그러나 어쨌든 피코 클리보다 조금 더 장황하게 보입니다.
Pete

2
나는 두 번째 @Pete ... 나는이 목록을 살펴 보았습니다.이 목록은 바닥에 묻혀있는 완전한 시간 낭비였습니다. 이것은 1 마일의 최고 답변이어야합니다. 잘 했어! Apache CLI 또는 대부분의 다른 파서에서 내 요구 사항을 처리 할 수 ​​없습니다. 그들은 picocli에게도 도전했지만, 내가 원하는 구문 / 동작에 가장 가까운 것을 줄 수 있었고 실제로 필요한 것을 해킹 할만 큼 유연했습니다. 보너스로 ANSI 기능 덕분에 멋지게 보입니다.
Shai Almog

@ShaiAlmog 가장 인기있는 답변은 10 살이며 구식입니다. 2019 년 Commons CLI를 추천하는 것이 잘못된 IMHO라는 데 동의합니다. 고려하시기 바랍니다 재 작성 날짜에 더 만들기 위해 상단의 대답을.
Remko Popma

나는 당신이 이미 그것을 시도했다고 생각합니다, 그게 나에게도 효과가 없을 것이라고 생각합니다 ... 1Picoli와 같은 이름을 선택했다면 알파벳 순서로 세 번째 대답을 정렬 할 수 있습니다 ;-)
Shai Almog

변경 사항이 되돌려 진 이유는 본인이 소속을 공개하지 않았기 때문이라고 생각합니다 (저는 저자입니다). 다른 사람들에게는 그 문제가 없어야합니다.
Remko Popma

23

JOpt를 사용하고 꽤 편리하다는 것을 알았습니다 : http://jopt-simple.sourceforge.net/

첫 페이지에는 약 8 개의 대체 라이브러리 목록이 있으며, 확인하고 필요에 가장 적합한 라이브러리를 선택하십시오.


21

누군가가 최근에 주석 기반의 args4j를 지적했습니다 . 난 정말 좋아!


1
Args4J의 경우 +1! 매우 인간 친화적이고 유연하며 이해할 수 있습니다. Java CLI 앱을 빌드하기위한 표준 이동 라이브러리이어야한다고 생각합니다.
Zearin

JCommander가 할 수없는 정렬되지 않은 (필드 순서로 정렬 된) 사용법 인쇄를 처리 할 수 ​​있고 더 유연합니다.
Daniel Hári 2012

@ DanielHári이 기능은 JCommander (2017 년 2 월 하순)에 추가되었습니다.
Nathan

9

이것은 Bazel 프로젝트의 일부로 오픈 소스 된 Google의 명령 줄 구문 분석 라이브러리입니다. 개인적으로 나는 그것이 가장 훌륭하고 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. 짧고 긴 / 설명 옵션을 어떻게 정의하는지
모르겠습니다


8

나는 당신이 다음과 같은 것을 찾고 있다고 생각합니다 : http://commons.apache.org/cli

Apache Commons CLI 라이브러리는 명령 행 인터페이스 처리를위한 API를 제공합니다.


7

나는 여기에있는 대부분의 사람들이 내 방식을 싫어하는 이유를 천만 가지의 이유를 발견 할 것입니다. 나는 일을 간단하게 유지하고 싶기 때문에 '='를 사용하여 키를 값과 분리하고 다음과 같이 HashMap에 저장합니다.

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

사용자가 인수를 잊었거나 잘못된 인수를 사용한 경우 사용자를 돕기 위해 항상 예상 인수로 목록을 유지할 수 있습니다. 그러나 너무 많은 기능을 원할 경우이 솔루션은 어쨌든 적합하지 않습니다.


7

아마도 이것들

  • Java 용 JArgs 명령 행 옵션 구문 분석 스위트 -이 작은 프로젝트는 Java 프로그래머의 사용을 위해 편리하고 컴팩트하며 사전 패키지화되고 포괄적으로 문서화 된 명령 행 옵션 구문 분석기 스위트를 제공합니다. 처음에는 GNU 스타일 'getopt'와 호환되는 구문 분석이 제공됩니다.

  • ritopt, Java 용 Ultimate Options Parser- 여러 명령 행 옵션 표준이 제안되었지만 ritopt는 opt 패키지에 규정 된 규칙을 따릅니다.






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;

   // ...
}

대단합니다 :).
John Humphreys-

3

내가 찾은 것이 Argparse4j가 최고입니다. 그것은 매우 편리하고 강력한 파이썬의 argparse 라이브러리를 모방합니다.


2

가볍고 (jar size ~ 20 kb) 사용하기 쉬운 것을 원한다면 argument-parser를 사용해보십시오 . 대부분의 유스 케이스에서 사용할 수 있으며 인수에서 배열 지정을 지원하며 다른 라이브러리에 종속되지 않습니다. 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 라이브러리는 스레드로부터 안전하지 않습니다. 그러나 명령 줄 구문 분석은 일반적으로 응용 프로그램 시작 중 단일 스레드에서 수행되며 매개 변수에 따라 다른 스레드가 시작될 수 있다고 가정합니다.
Alexey Ivanov

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.