web-dev-qa-db-fra.com

Analyse des arguments dans un programme de ligne de commande Java

Et si je voulais analyser ceci:

Java MyProgram -r opt1 -S opt2 arg1 arg2 arg3 arg4 --test -A opt3

Et le résultat que je veux dans mon programme est:

regular Java args[]  of size=4
org.Apache.commons.cli.Options[]  of size=3
org.Apache.commons.cli.Options[] #2 of size=1

Je préférerais utiliser Apache Commons CLI , mais la documentation est un peu peu claire sur le cas que je présente ci-dessus. Plus précisément, la documentation ne vous explique pas comment gérer les options du troisième type que je spécifie ci-dessous:

1. options with a "-" char
2. options with a "--" char
3. options without any marker, or "bare args"

Je souhaite que la CLI d’Apache Commons fonctionne, mais puisse TOUJOURS passer des arguments réguliers au programme si ces arguments n’ont pas de préfixe d’option. Peut-être que c'est le cas, mais la documentation ne le dit pas alors que je l'ai lue ...

43
djangofan

Vous pouvez simplement le faire manuellement.

NB: pourrait être préférable d'utiliser un HashMap au lieu d'une classe interne pour les opts.

/** convenient "-flag opt" combination */
private class Option {
     String flag, opt;
     public Option(String flag, String opt) { this.flag = flag; this.opt = opt; }
}

static public void main(String[] args) {
    List<String> argsList = new ArrayList<String>();  
    List<Option> optsList = new ArrayList<Option>();
    List<String> doubleOptsList = new ArrayList<String>();

    for (int i = 0; i < args.length; i++) {
        switch (args[i].charAt(0)) {
        case '-':
            if (args[i].length < 2)
                throw new IllegalArgumentException("Not a valid argument: "+args[i]);
            if (args[i].charAt(1) == '-') {
                if (args[i].length < 3)
                    throw new IllegalArgumentException("Not a valid argument: "+args[i]);
                // --opt
                doubleOptsList.add(args[i].substring(2, args[i].length));
            } else {
                if (args.length-1 == i)
                    throw new IllegalArgumentException("Expected arg after: "+args[i]);
                // -opt
                optsList.add(new Option(args[i], args[i+1]));
                i++;
            }
            break;
        default:
            // arg
            argsList.add(args[i]);
            break;
        }
    }
    // etc
}
29
Charles Goodwin

Utilisez la bibliothèque CLI Apache Commons commandline.getArgs () pour obtenir arg1, arg2, arg3 et arg4. Voici du code:



    import org.Apache.commons.cli.CommandLine;
    import org.Apache.commons.cli.Option;
    import org.Apache.commons.cli.Options;
    import org.Apache.commons.cli.Option.Builder;
    import org.Apache.commons.cli.CommandLineParser;
    import org.Apache.commons.cli.DefaultParser;
    import org.Apache.commons.cli.ParseException;

    public static void main(String[] parameters)
    {
        CommandLine commandLine;
        Option option_A = Option.builder("A")
            .required(true)
            .desc("The A option")
            .longOpt("opt3")
            .build();
        Option option_r = Option.builder("r")
            .required(true)
            .desc("The r option")
            .longOpt("opt1")
            .build();
        Option option_S = Option.builder("S")
            .required(true)
            .desc("The S option")
            .longOpt("opt2")
            .build();
        Option option_test = Option.builder()
            .required(true)
            .desc("The test option")
            .longOpt("test")
            .build();
        Options options = new Options();
        CommandLineParser parser = new DefaultParser();

        String[] testArgs =
        { "-r", "opt1", "-S", "opt2", "arg1", "arg2",
          "arg3", "arg4", "--test", "-A", "opt3", };

        options.addOption(option_A);
        options.addOption(option_r);
        options.addOption(option_S);
        options.addOption(option_test);

        try
        {
            commandLine = parser.parse(options, testArgs);

            if (commandLine.hasOption("A"))
            {
                System.out.print("Option A is present.  The value is: ");
                System.out.println(commandLine.getOptionValue("A"));
            }

            if (commandLine.hasOption("r"))
            {
                System.out.print("Option r is present.  The value is: ");
                System.out.println(commandLine.getOptionValue("r"));
            }

            if (commandLine.hasOption("S"))
            {
                System.out.print("Option S is present.  The value is: ");
                System.out.println(commandLine.getOptionValue("S"));
            }

            if (commandLine.hasOption("test"))
            {
                System.out.println("Option test is present.  This is a flag option.");
            }

            {
                String[] remainder = commandLine.getArgs();
                System.out.print("Remaining arguments: ");
                for (String argument : remainder)
                {
                    System.out.print(argument);
                    System.out.print(" ");
                }

                System.out.println();
            }

        }
        catch (ParseException exception)
        {
            System.out.print("Parse error: ");
            System.out.println(exception.getMessage());
        }
    }

59
DwB

J'aime celui la. Simple et vous avez plus d'un paramètre pour chaque argument:

final Map<String, List<String>> params = new HashMap<>();

List<String> options = null;
for (int i = 0; i < args.length; i++) {
    final String a = args[i];

    if (a.charAt(0) == '-') {
        if (a.length() < 2) {
            System.err.println("Error at argument " + a);
            return;
        }

        options = new ArrayList<>();
        params.put(a.substring(1), options);
    }
    else if (options != null) {
        options.add(a);
    }
    else {
        System.err.println("Illegal parameter usage");
        return;
    }
}

Par exemple:

-arg1 1 2 --arg2 3 4

System.out.print(params.get("arg1").get(0)); // 1
System.out.print(params.get("arg1").get(1)); // 2
System.out.print(params.get("-arg2").get(0)); // 3
System.out.print(params.get("-arg2").get(1)); // 4
12
user1079877

Voici la solution @DwB mise à niveau vers la conformité à la CLI 1.3.1 de Commons (remplace les composants obsolètes OptionBuilder et GnuParser). La documentation Apache utilise des exemples qui dans la vie réelle ont des arguments non marqués/nus mais les ignorent. Merci à @DwB pour avoir montré comment cela fonctionne.

import org.Apache.commons.cli.CommandLine;
import org.Apache.commons.cli.CommandLineParser;
import org.Apache.commons.cli.DefaultParser;
import org.Apache.commons.cli.HelpFormatter;
import org.Apache.commons.cli.Option;
import org.Apache.commons.cli.Options;
import org.Apache.commons.cli.ParseException;

public static void main(String[] parameters) {
    CommandLine commandLine;
    Option option_A = Option.builder("A").argName("opt3").hasArg().desc("The A option").build();
    Option option_r = Option.builder("r").argName("opt1").hasArg().desc("The r option").build();
    Option option_S = Option.builder("S").argName("opt2").hasArg().desc("The S option").build();
    Option option_test = Option.builder().longOpt("test").desc("The test option").build();
    Options options = new Options();
    CommandLineParser parser = new DefaultParser();

    options.addOption(option_A);
    options.addOption(option_r);
    options.addOption(option_S);
    options.addOption(option_test);

    String header = "               [<arg1> [<arg2> [<arg3> ...\n       Options, flags and arguments may be in any order";
    String footer = "This is DwB's solution brought to Commons CLI 1.3.1 compliance (deprecated methods replaced)";
    HelpFormatter formatter = new HelpFormatter();
    formatter.printHelp("CLIsample", header, options, footer, true);    

    String[] testArgs =
            { "-r", "opt1", "-S", "opt2", "arg1", "arg2",
                    "arg3", "arg4", "--test", "-A", "opt3", };

    try
    {
        commandLine = parser.parse(options, testArgs);

        if (commandLine.hasOption("A"))
        {
            System.out.print("Option A is present.  The value is: ");
            System.out.println(commandLine.getOptionValue("A"));
        }

        if (commandLine.hasOption("r"))
        {
            System.out.print("Option r is present.  The value is: ");
            System.out.println(commandLine.getOptionValue("r"));
        }

        if (commandLine.hasOption("S"))
        {
            System.out.print("Option S is present.  The value is: ");
            System.out.println(commandLine.getOptionValue("S"));
        }

        if (commandLine.hasOption("test"))
        {
            System.out.println("Option test is present.  This is a flag option.");
        }

        {
            String[] remainder = commandLine.getArgs();
            System.out.print("Remaining arguments: ");
            for (String argument : remainder)
            {
                System.out.print(argument);
                System.out.print(" ");
            }

            System.out.println();
        }

    }
    catch (ParseException exception)
    {
        System.out.print("Parse error: ");
        System.out.println(exception.getMessage());
    }

}

Sortie:

usage: CLIsample [-A <opt3>] [-r <opt1>] [-S <opt2>] [--test]
                 [<arg1> [<arg2> [<arg3> ...
       Options, flags and arguments may be in any order
 -A <opt3>   The A option
 -r <opt1>   The r option
 -S <opt2>   The S option
    --test   The test option
This is DwB's solution brought to Commons CLI 1.3.1 compliance (deprecated
methods replaced)
Option A is present.  The value is: opt3
Option r is present.  The value is: opt1
Option S is present.  The value is: opt2
Option test is present.  This is a flag option.
Remaining arguments: arg1 arg2 arg3 arg4
3
Peter DeGregorio

Vous pouvez utiliser https://github.com/jankroken/commandline , voici comment procéder:

Pour que cet exemple fonctionne, je dois émettre des hypothèses sur la signification des arguments - il suffit de choisir quelque chose ici ...

-r opt1 => replyAddress=opt1
-S opt2 arg1 arg2 arg3 arg4 => subjects=[opt2,arg1,arg2,arg3,arg4]
--test = test=true (default false)
-A opt3 => address=opt3

ceci peut alors être configuré de la manière suivante:

public class MyProgramOptions {
  private String replyAddress;
  private String address;
  private List<String> subjects;
  private boolean test = false;

  @ShortSwitch("r")
  @LongSwitch("replyAddress") // if you also want a long variant. This can be skipped
  @SingleArgument
  public void setReplyAddress(String replyAddress) {
    this.replyAddress = replyAddress;
  }

  @ShortSwitch("S")
  @AllAvailableArguments
  public void setSubjects(List<String> subjects) {
    this.subjects = subjects;
  }

  @LongSwitch("test")
  @Toggle(true)
  public void setTest(boolean test) {
    this.test = test;
  }

  @ShortSwitch("A")
  @SingleArgument
  public void setAddress(String address) {
    this.address = address;
  }

  // getters...
}

et ensuite dans la méthode principale, vous pouvez simplement faire:

public final static void main(String[] args) {
  try {
    MyProgramOptions options = CommandLineParser.parse(MyProgramOptions.class, args, OptionStyle.SIMPLE);

    // and then you can pass options to your application logic...

  } catch
    ...
  }
}
2
xeno

Vous pouvez utiliser l'artefact refcodes-console sur refcodes-console sur REFCODES.ORG:

Option<String> r     = new StringOptionImpl( "-r", null, "opt1", "..." );
Option<String> s     = new StringOptionImpl( "-S", null, "opt2", "..." );
Operand<String> arg1 = new StringOperandImpl( "arg1", "..." );
Operand<String> arg2 = new StringOperandImpl( "arg2", "..." );
Operand<String> arg3 = new StringOperandImpl( "arg3", "..." );
Operand<String> arg4 = new StringOperandImpl( "arg4", "..." );
Switch test          = new SwitchImpl( null, "--test", "..." );
Option<String> a     = new StringOptionImpl( "-A", null, "opt3", "..." );
Condition theRoot    = new AndConditionImpl( r, s, a, arg1, arg2, arg3, arg4,
    test );

Créez votre analyseur d'arguments ArgsParserImpl avec votre condition racine:

ArgsParser theArgsParser = new ArgsParserImpl( theRoot );
theArgsParser.setName( "MyProgramm" );
theArgsParser.setSyntaxNotation( SyntaxNotation.GNU_POSIX );

Au-dessus de vous définir votre syntaxe, ci-dessous vous appelez l'analyseur:

theArgsParser.printUsage();
theArgsParser.printSeparatorLn();
theArgsParser.printOptions();
theArgsParser.evalArgs( new String[] {
    "-r", "RRRRR", "-S", "SSSSS", "11111", "22222", "33333", "44444", 
    "--test", "-A", "AAAAA"
} );

Si vous avez fourni de bonnes descriptions, theArgsParser.printUsage() vous montrera même la jolie utilisation imprimée:

Usage: MyProgramm -r <opt1> -S <opt2> -A <opt3> arg1 arg2 arg3 arg4 --test

Dans l'exemple ci-dessus, tous les arguments définis doivent être passés par l'utilisateur, sinon l'analyseur détectera un usage incorrect. Si le paramètre --test doit être optional (ou tout autre argument), affectez theRoot comme suit:

theRoot = new AndConditionImpl (r, s, a, arg1, arg2, arg3, arg4, new OptionalImpl (test));

Ensuite, votre syntaxe ressemble à ceci:

Usage: MyProgramm -r <opt1> -S <opt2> -A <opt3> arg1 arg2 arg3 arg4 [--test]

L’exemple complet correspondant à votre cas se trouve dans le StackOverFlowExamle . Vous pouvez utiliser les conditions AND, OR, XOR et tout type d'imbrication ... espérons que cela vous aidera.

Évaluez les arguments analysés comme suit: r.getValue() ); ou if (test.getValue() == true) ...:

LOGGER.info( "r    :=" + r.getValue() );
LOGGER.info( "S    :=" + s.getValue() );
LOGGER.info( "arg1 :=" + arg1.getValue() );
LOGGER.info( "arg2 :=" + arg2.getValue() );
LOGGER.info( "arg3 :=" + arg3.getValue() );
LOGGER.info( "arg4 :=" + arg4.getValue() );
LOGGER.info( "test :=" + test.getValue() + "" );
LOGGER.info( "A    :=" + a.getValue() );
1
REFCODES.ORG

Ok, merci à Charles Goodwin pour le concept. Voici la réponse:

import Java.util.*;
public class Test {

  public static void main(String[] args) {
     List<String> argsList  = new ArrayList<String>();  
     List<String> optsList  = new ArrayList<String>();
     List<String> doubleOptsList  = new ArrayList<String>();
     for (int i=0; i < args.length; i++) {
         switch (args[i].charAt(0)) {
         case '-':
             if (args[i].charAt(1) == '-') {
                 int len = 0;
                 String argstring = args[i].toString();
                 len = argstring.length();
                 System.out.println("Found double dash with command " +
                     argstring.substring(2, len) );
                 doubleOptsList.add(argstring.substring(2, len));           
             } else {
                 System.out.println("Found dash with command " + 
                   args[i].charAt(1) + " and value " + args[i+1] );   
                 i= i+1;
                 optsList.add(args[i]);      
             }           
         break;         
         default:            
         System.out.println("Add a default arg." );
         argsList.add(args[i]);
         break;         
         }     
     } 
  } 

}
0
djangofan

Code simple pour la ligne de commande en Java:

class CMDLineArgument
{
    public static void main(String args[])
    {
        String name=args[0];
        System.out.println(name);
    }
}
0
Mayur Chudasama