解析字符串就好像它是带有参数和选项的命令一样

时间:2010-09-07 17:32:26

标签: java command-line command-line-parsing

我有这个Java枚举:

public enum Commands
{
    RESIZE_WINDOW("size -size"),
    CREATE_CHARACTER("create-char -name"),
    NEW_SCENE("scene -image"),
    DIALOG("d -who -words"),
    PLAY_SOUND("sound -file --blocking=false"),
    FADE_TO("fade-to -file"),
    WAIT("w -length=auto");
}

我希望能够解析这些字符串并提取:

  • 命令名称(例如create-char
  • 必需参数(例如-name
  • 可选选项,默认值(例如--blocking=false

我看了org.apache.commons.cli,但是在第一个标准(不同的命令名称)上似乎失败了,而且非常详细。

任何图书馆建议?

(如果该上下文有帮助,这将用于解析脚本“语言”。)

编辑:脚本语言中的示例输入为d John "Hello World" - 多字文字用引号括起来。

1 个答案:

答案 0 :(得分:6)

您希望仅根据其“帮助描述符”构建大量CLI命令;一种DSL种。不要进行这种字符串解析,而是考虑以编程方式构建命令,其中有许多库(CLI只有一个)和优点。

您的示例已经非常复杂,需要再次查看CLI(或其中一个)。您显示必需和可选的args,每个args都具有无值或默认值(尽管没有指示'required'arg-values没有默认值,命令描述等),您仍然需要为命令行构建解析器本身,验证,调用处理程序的方法等......

下面是我找到的命令解析器列表。没有人会解析您的特定DSL,但它们将允许您以编程方式构建命令,解析它,经常验证并提供有意义的警告,帮助处理等。有些甚至使用对象上的注释来定义命令,理论上使维护更容易。

大多数是设计(并显示示例)来解析程序的参数,而不是大量的命令(natural-cli是一个例外)但是所有人都应该能够做到这一点 - 一个简单的类可以将解析和选项包装在一起:

static class CommandLine {
    HashMap<String,Options> options = new HashMap<String,Options>();

    public void register(String cmd, Options opts) {
        options.put(cmd, opts);
    }

    public void parse(String line) {
        // a better parser here would handle quoted strings
        String[] split = line.split("\\s");

        String cmd = split[0];
        String[] args = new String[split.length-1];
        if (args.length > 0)
            System.arraycopy(split, 1, args, 0, args.length);

        Options opts = options.get(cmd);
        if (opts == null) 
            ; // handle unknown command
        else {
            opts.parse(args);
            // handle results...
            opts.reset(); // required?
        }
    }
}

public static void main(String[] args) throws Exception {

    CommandLine cl = new CommandLine();
    cl.register("size", new Options());        // This will vary based on library Some
    cl.register("create-char", new Options()); // require subclasses, others use builder
    //...                                         pattern, or other means.

    BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    while (true) {
        cl.parse(in.readLine());
    }
}

其他图书馆

  • CLI
  • JewelCli:还使用注释,并允许列表和枚举值。示例看起来很有希望
  • natural-cli:允许cli使用“人类可读的信号”。似乎面向您的多个命令及其选项的目标,具有不同DSL和语法的albiet。
  • GNU Java Getopt:使用与上面相同的方法,尽管使用命令名称初始化Getopt对象。
  • JOpt Simple:声称“比其他所有人更简单”
  • JArgs
  • args4j:对为每个命令创建的单独类使用注释
  • JSAP
  • CLAJR:使用反射
  • CmdLn
  • ArgParser
  • JCommando:使用XML配置文件。
  • parse-cmd:使用Builder-pattern和方法链来构建参数
  • cli-parser:基于注释