Java'da komut satırı bağımsız değişkenlerini nasıl ayrıştırabilirim?


586

Java'da komut satırı bağımsız değişkenlerini ayrıştırmanın iyi bir yolu nedir?


4
Args4j ve nasıl kullanılacağı ile ilgili ayrıntılı bir örneğe bakın: martin-thoma.com/how-to-parse-command-line-arguments-in-java
Martin Thoma

Görünüşe göre bu partiye oldukça geç kaldım, ama Java için bir komut satırı bağımsız değişken işleyicisi yazdım ve GitHub: MainArgsHandler üzerine koydum . İş parçacığı kapalı gelince, bu çok yararlı bir iş parçacığı olduğunu düşünüyorum, ama muhtemelen genel programlama tartışma için Stack Exchange Programcılar sitesine geçirilmesi gerekir.
Bobulous

@RedGlyph - SO / SE'nin kurallarını basitleştirmesi gerekiyor gibi görünüyor. Sorusu olmalıydı: How to parse java command line arguments?. Ama hiç kimse bunu yapmak için kod yazmak istemiyor, bunun yerine bir araç kullanıyor. Ancak araçlar ve benzerleri aramak yapıcı değildir :(
AlikElzin-kilaka

6
Oy verildi reopening. @AlikElzin: Gerçekten de, denetleyici süreçlerini gözden geçirmeleri gerekiyor. Bu kadar çok soruyu kapatmak için bir rozet olduğundan şüpheleniyorum ve moderatör olmak istemez.
RedGlyph

8
Bu soru, kötü / tek satırlık cevaplar ve araç önerileri için bir bal küpüdür. Kapalı kalmalıdır.
JAL

Yanıtlar:


405

Bunları kontrol et:

Veya kendi etiketinizi alın:


Örneğin,commons-cli 2 dize bağımsız değişkenini ayrıştırmak için bu yöntemi kullanırsınız :

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

    }

}

komut satırından kullanım:

$> 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
Diğer birçok Apache kütüphanesinden farklı olarak Apache CLI'nin bağımlılığı olmadığını unutmayın.
Vladimir Dyuzhev

9
Birçok apache-commons projesinin dezavantajı, daha az ve daha az taahhüt alması ve sonunda ortadan kalkmasıdır.
Brett Ryan

4
İşte Apache CLI projesi için hızlı bir şekilde kullanmaya nasıl başlayacağınızla ilgili "Kullanım Senaryoları" sayfası: commons.apache.org/cli/usage.html
Brad Parks

Args4J / JCommander gibi bir arayüz olduğunu ve yöntemlere açıklama eklemeniz dışında tam olarak var olduğunu düşünmüyorum? "Ürkütücü başlangıç" özel alanları olan sınıflar düşkün büyümek asla ...
Trejkaz

5
@RemkoPopma picocli kütüphaneniz harika görünüyor ve bunu yaptığınız için teşekkür ederim. Ancak burada ve diğer yayınlarda ne yaptığınızı düşünüyoruz (kabul edilen cevapları düzenleyin ve kitaplığın en üstündeki kitabın orijinal yazarından değil, libanızdan bir düzenleme bile ifşa etmeden en üstte kitaplığınızı tanıtın) ılımlılık güçlerinizin korkunç bir kötüye kullanımı. Bunu diğer modlara işaretlemek.
Alexander Malakhov

312

Daha yeni JCommander'e bir göz atın .

Ben yarattım. Soru veya özellik isteği almaktan mutluluk duyuyorum.


7
JCommander gibi sevindim :-) Bayrakların nasıl işlendiğine çok fazla semantik eklemek istemedim, bu yüzden kullandığınız ek açıklamalara eşanlamlıları eklemeniz gerekiyor: @Parametre (names = {"-h", "- -help "}) Bunun makul bir uzlaşma olduğunu düşündüm.
Cedric Beust

14
Harika bir araç. Güçlü, esnek ve sinir bozucu, geleneksel seçenek ayrıştırıcılarıyla uğraşmak zorunda değilsiniz.
IanGilham

3
Evet, sanırım JCommander'i yazdığınız gibi kendi komut satırı argüman ayrıştırıcımı yazardım. Harika iş.
SRG

9
@CedricBeust, bu harika bir kütüphane, çok teşekkür ederim. Kendi Args sınıflarımızı tanımlayabildiğimizden, daha sonra bir kütüphane sınıfına bağımlı olmadan iletilebildiğimiz için onu son derece esnek hale getirir.
Brett Ryan

2
rekabeti sudan atıyor!
Marcus Junius Brutus

235

7
@ Flynn Flynn hehe, içinde oldukça şaşırtıcı ve ilginç şekilli tekerlekler var. Sanırım bunu yapmanın birden fazla yolu olduğunu göstermenin çoğunlukla zararsız bir yolu!
lexicalscope

14
JOpt Simple'ın yazarının çok benzer bir listeye sahip olduğunu not ediyorum! Metne ihtiyacımız olan şey, bu listeleri bir tabloya dönüştürmek, özellikleri ve ilgi çekici noktaları listelemek, böylece yoksul kullanıcılar bilinçli bir seçim yapabilirler.
Tom Anderson

1
Oluşturduğum Rop - github.com/ryenus/rop , düz sınıflar ve alanları üzerinden komutlar ve seçenekler beyan açıklama tabanlı bir çözüm, inşa komut satırı çözümleyicinin hemen hemen bir bildirim yolu vardır. Git (single-cmd) veya Maven (multi-cmd) gibi uygulamalar oluşturabilir.
ryenus

8
Listelenen projelerin çoğu aslında terkedilebilir. Listeden geçtikten sonra, aktif olarak tutulan ve popüler olan büyük vurucuların ortak müşterek, jcommander, args4j, jopt-simple ve picocli gibi göründüğünü söyleyebilirim. Argparse4j ve cli-parser gibi şeylerin yazarlarından özür - Biraz keyfi bir sıralama yapmak zorunda kaldım ve listedeki diğer beş proje de popüler ve hala aktif geliştirme aşamasında.
George Hawkins

2
Birisine her ayrıştırıcının son kararlı yayın tarihini eklemesi için meydan okuyorum.
Kızak

50

Bu 2020, Commons CLI daha iyi yapmak için zaman ... :-)

Kendi Java komut satırı ayrıştırıcısını oluşturmalı veya bir kütüphane mi kullanmalısınız?

Birçok küçük yardımcı program benzeri uygulama, ek harici bağımlılığı önlemek için muhtemelen kendi komut satırı ayrıştırmalarını döndürür. picocli ilginç bir alternatif olabilir.

Picocli, güçlü, kullanıcı dostu, GraalVM özellikli komut satırı uygulamaları kolaylıkla oluşturmak için modern bir kütüphane ve çerçevedir. Bir bağımlılık eklemekten kaçınmak için uygulamaların kaynak olarak dahil edebilmesi için 1 kaynak dosyasında yaşar.

Renkleri, otomatik tamamlamayı, alt komutları ve daha fazlasını destekler. Java ile yazılmış, Groovy, Kotlin, Scala vb.

ANSI renklerle minimum kullanım yardımı

Özellikleri:

  • Ek açıklama tabanlı: bildirici , yinelemeyi önler ve programcı amacını ifade eder
  • Kullanışlı: kullanıcı girişini ayrıştırın ve iş mantığınızı bir kod satırı ile çalıştırın
  • Her şeyi güçlü bir şekilde yazdım - komut satırı seçenekleri ve konum parametreleri
  • POSIX kümelenmiş kısa seçenekleri ( <command> -xvfInputFileyanı sıra <command> -x -v -f InputFile)
  • İnce taneli kontrolü : minimum, maksimum ve parametrelerin değişken sayısını sağlayan bir Arity modeli, örneğin "1..*","3..5"
  • Alt komutlar (gelişigüzel derinliğe yuvalanabilir)
  • Zengin özelliklere sahip : oluşturulabilir arg grupları, alıntılanmış değişkenleri bölme, tekrarlanabilir alt komutlar ve daha fazlası
  • Kullanıcı dostu : kullanım yardım mesajı , kullanıcı üzerindeki bilişsel yükü azaltmak için kullanım yardımının geri kalan kısmındaki seçenek adları gibi önemli öğeleri karşılaştırmak için renkleri kullanır
  • Uygulamanızı GraalVM yerel resmi olarak dağıtma
  • İle İşleri Java 5 ve üzeri
  • Kapsamlı ve titiz dokümantasyon

Kullanım yardım mesajı ek açıklamalarla (programlama olmadan) kolayca özelleştirilebilir. Örneğin:

Genişletilmiş kullanım yardım mesajı( kaynak )

Hangi kullanım yardım mesajlarının mümkün olduğunu göstermek için bir ekran görüntüsü daha eklemeye dayanamadım. Kullanım yardımı, uygulamanızın yüzüdür, bu yüzden yaratıcı olun ve eğlenin!

picocli demosu

Feragatname: Piknik oluşturdum. Geri bildirim veya sorular çok hoş geldiniz.


5
Saf dahi! Bu cevabın dibine gömülmesi bir utanç. Apache Commons CLI ayrıntılı, arabacı ve uzun zamandır güncellenmemiş. Google'ın CLI ayrıştırıcısını kullanmak istemiyorum çünkü komut satırı bağımsız değişkeni kullanım geçmişime dayalı hedefli reklamlar istemiyorum. Ama yine de picocli'den biraz daha ayrıntılı görünüyor.
Pete

2
@Pete'i buraya ikinci olarak koydum ... Bu listeyi gözden geçirdim. Bu bir milin en büyük yanıtı olmalı. İyi iş! Gereksinimlerim apache CLI veya bu diğer ayrıştırıcıların çoğu tarafından karşılanamadı. Onlar bile picocli için zorlu ama bana istediğim sözdizimi / davranış için en yakın şey vermek mümkün ve gerçekten ne istediğini kesmek için esnek. Bir bonus olarak ANSI şeyler sayesinde harika görünüyor.
Shai Almog

@ShaiAlmog En çok oy alan cevap 10 yaşında ve modası geçmiş. 2019'da Commons CLI'yi tavsiye etmenin IMHO'yu yanıltıcı olduğunu kabul ediyorum. Daha güncel hale getirmek için lütfen en iyi yanıtı yeniden yazmayı düşünün .
Remko Popma

Bunu zaten denediğini görüyorum, benim için de işe yarayacağını sanmıyorum ... 1Picoli gibi bir isim seçseydin 3. cevabı alfabetik olarak sıralayabilirdik ;-)
Shai Almog

Değişikliğimin geri çevrilmesinin sebebinin bağlılığımı açıklamamış olmam (sanırım yazarım). Diğer insanların bu sorunu yaşamaması gerekir.
Remko Popma

23

JOpt kullandım ve oldukça kullanışlı buldum: http://jopt-simple.sourceforge.net/

Ön sayfa ayrıca yaklaşık 8 alternatif kütüphanenin bir listesini sunar, kontrol eder ve ihtiyaçlarınıza en uygun olanı seçer.


21

Birisi son zamanlarda ek açıklama tabanlı olan args4j'yi işaret etti . Gerçekten beğendim!


1
Args4J için +1! Son derece insan dostu, esnek ve anlaşılabilir. Java CLI uygulamaları oluşturmak için standart go-to kütüphanesi olması gerektiğini düşünüyorum.
Zearin

Sırasız (saha sırasına göre sıralanmış) kullanım baskısını işleyebilmesi, JCommander'ın yapamadığı ve daha esnektir.
Daniel Hári

@ DanielHári Sadece bilgi amaçlı olarak, bu işlevsellik JCommander'de eklendi (bazen 2017'nin sonlarında).
Nathan

9

Bu, Bazel projesinin bir parçası olarak açık kaynaklı Google'ın komut satırı ayrıştırma kütüphanesidir. Şahsen bunun en iyisi olduğunu düşünüyorum ve Apache CLI'den çok daha kolay.

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

Kurulum

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

Uzman

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

kullanım

(Leri) OptionsBasenizi genişleten ve tanımlayan bir sınıf oluşturun @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;

}

Argümanları ayrıştırın ve kullanın.

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


Merhaba Paul. Cevabınızı veya proje belgelerinizi okuduğumda ne tür bir komut satırı işleyebileceğine dair hiçbir fikrim yok. Örneğin, böyle bir şey sağlayabilirsiniz myexecutable -c file.json -d 42 --outdir ./out. Ve kısa / uzun / açıklama seçeneklerini nasıl tanımladığınızı görmüyorum ... Şerefe
olibre



7

Buradaki insanların çoğunun benim yolumu sevmemek için 10 milyon neden bulacağını biliyorum, ama boş. Ben şeyleri basit tutmak istiyorum, bu yüzden sadece '=' kullanarak anahtarı değerden ayırmak ve böyle bir HashMap saklamak:

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

Her zaman beklediğiniz argümanların bir listesini tutabilirsiniz, bir argümanı unutması veya yanlış bir kullanması durumunda kullanıcıya yardımcı olmak için ... Ancak, çok fazla özellik istiyorsanız bu çözüm zaten sizin için değildir.


7

Belki bunlar






4

Zaten Spring Boot kullanıyorsanız, argüman ayrıştırma kutunun dışına çıkar.

Başlangıçtan sonra bir şey çalıştırmak istiyorsanız, ApplicationRunnerarayüzü uygulayın:

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

Kişisel runbağlam başarıyla çalıştırılması ardından yöntemi çağrılır.

Uygulama bağlamınızı tetiklemeden önce bağımsız değişkenlere erişmeniz gerekiyorsa, yalnızca uygulama bağımsız değişkenlerini manuel olarak ayrıştırabilirsiniz:

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

}

Ve son olarak, bir fasulye içindeki argümanlarınıza erişmeniz gerekiyorsa, şunları enjekte edin ApplicationArguments:

@Component
public class MyBean {

   @Autowired
   private ApplicationArguments arguments;

   // ...
}

Bu harika :).
John Humphreys - w00te

3

Argparse4j bulduğum en iyisidir. Python'un çok kullanışlı ve güçlü argparse libaryerini taklit eder.


2

Hafif (kavanoz boyutu ~ 20 kb) ve kullanımı basit bir şey istiyorsanız, bağımsız değişken ayrıştırıcıyı deneyebilirsiniz . Çoğu kullanım durumunda kullanılabilir, argümanda dizileri belirtmeyi destekler ve başka herhangi bir kütüphaneye bağımlılığı yoktur. Java 1.5 veya üstü için çalışır. Aşağıdaki alıntı, nasıl kullanılacağına dair bir örnek göstermektedir:

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

Daha fazla örnek burada bulunabilir


1
Bağlantı öldü. Projeni öldürdün mü? :-(
beldaz

2

Apache Common CLINon-threadsafe olduğu için kütüphane kullanmanızı tavsiye etmem .

Dahili çalışma yapmak için statik değişkenler ve yöntemler içeren durumsal sınıflar kullanır (örn. OptionBuilder) Ve yalnızca tek iş parçacıklı güçlü kontrol edilen durumlarda kullanılmalıdır.


18
CLI kütüphanesinin iş parçacığı için güvenli olmadığını unutmayın. Ancak, komut satırı ayrıştırma genellikle uygulama başlatma sırasında tek bir iş parçacığında yapılır ve sonra parametrelere bağlı olarak diğer iş parçacıkları başlatılabilir varsayalım.
Alexey Ivanov

0

Daha önce bahsedilen yorumlardan biri olarak ( https://github.com/pcj/google-options ) başlamak için iyi bir seçim olacaktır.

Eklemek istediğim bir şey:

1) Ayrıştırıcı yansıması hatasıyla karşılaşırsanız, lütfen guava'nın daha yeni bir sürümünü kullanmayı deneyin. benim durumumda:

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) Komut satırını çalıştırırken:

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

3) Kullanım yardımına ihtiyacınız olduğunda, şunu yazın:

bazel run path/to/your:project -- --help

-1
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.