53

对于解析播放器命令,我最常使用split方法通过分隔符拆分字符串,然后通过一系列ifs 或switches 找出其余部分。在 Java 中解析字符串有哪些不同的方法?

4

15 回答 15

19

我真的很喜欢正则表达式。只要命令字符串相当简单,您就可以编写一些正则表达式,这些正则表达式可能需要几页代码来手动解析。

我建议您查看http://www.regular-expressions.info以获得对正则表达式的良好介绍,以及 Java 的具体示例。

于 2008-08-05T23:54:05.533 回答
17

我假设您正在尝试使命令界面尽可能宽容。如果是这种情况,我建议您使用类似于此的算法:

  1. 读入字符串
    • 将字符串拆分为标记
    • 使用字典将同义词转换为通用形式
    • 例如,将“hit”、“punch”、“strike”和“kick”全部转换为“hit”
    • 在无序、包容的基础上执行操作
    • 无序——“打猴子的脸”和“打猴子的脸”是一回事
    • 包容性- 如果命令应该是“打猴子的脸”并且他们提供“打猴子”,你应该检查有多少命令匹配。如果只有一个命令,请执行此操作。拥有命令优先级甚至可能是一个好主意,即使有匹配项,它也会执行最高操作。
于 2008-08-06T00:42:00.817 回答
13

手动解析很有趣……一开始:)

实际上,如果命令不是很复杂,您可以像在命令行解释器中使用的那样对待它们。您可以使用一个库列表:http: //java-source.net/open-source/command-line。我认为您可以从apache commons CLIargs4j(使用注释)开始。它们有据可查,使用起来非常简单。它们会自动处理解析,您唯一需要做的就是读取对象中的特定字段。

如果您有更复杂的命令,那么创建正式语法可能是一个更好的主意。有一个非常好的库,带有图形编辑器、调试器和语法解释器。它被称为ANTLR(和编辑器ANTLRWorks),它是免费的:)还有一些示例语法和教程。

于 2008-08-30T22:26:00.180 回答
7

我会看一下Zork的Java 迁移,并倾向于一个简单的自然语言处理器(由标记化或正则表达式驱动),如下所示(来自此链接):

    公共静态布尔simpleNLP(字符串输入行,字符串关键字[])
    {
        诠释我;
        int maxToken = 关键字.长度;
        到,从;
        如果(输入线长度()=输入线长度())返回假;// 检查空行和空行
        而(到 >=0 )
        {
            to = inputline.indexOf(' ',from);
            如果(到 > 0){
                lexed.addElement(inputline.substring(from,to));
                从=到;
                而(inputline.charAt(来自)==''
                && from =keywords.length) { status = true; 休息;}
            }
        }
        返回状态;
    }

...

在我的书中,任何让程序员有理由再次关注 Zork 的东西都很好,只要注意 Grues。

...

于 2008-08-06T00:16:25.020 回答
6

Sun 本身建议远离 StringTokenizer 并改用 String.spilt 方法。

您还需要查看 Pattern 类。

于 2008-08-06T16:14:45.460 回答
6

再次投票给 ANTLR/ANTLRWorks。如果您创建文件的两个版本,一个带有用于实际执行命令的 Java 代码,另一个没有(仅带有语法),那么您就有了该语言的可执行规范,这对于测试非常有用,对文档来说是一个福音,如果您决定移植它,可以节省大量时间。

于 2008-08-31T01:38:29.890 回答
4

如果这是为了解析命令行,我建议使用Commons Cli

Apache Commons CLI 库提供了一个用于处理命令行界面的 API。

于 2008-08-31T01:05:38.457 回答
4

试试JavaCC一个 Java 解析器生成器。

它有很多解释语言的特性,并且在 Eclipse 上得到很好的支持。

于 2008-08-31T19:45:45.020 回答
2

@CodingTheWheel 继承你的代码,稍微清理一下并通过 eclipse ( ctrl++ shift)f并插入到这里:)

包括每行前面的四个空格。

public static boolean simpleNLP(String inputline, String keywords[]) {
    if (inputline.length() < 1)
        return false;

    List<String> lexed = new ArrayList<String>(); 
    for (String ele : inputline.split(" ")) {
        lexed.add(ele);
    }


    boolean status = false;
    to = 0;
    for (i = 0; i < lexed.size(); i++) {
        String s = (String) lexed.get(i);
        if (s.equalsIgnoreCase(keywords[to])) {
            to++;
            if (to >= keywords.length) {
                status = true;
                break;
            }
        }
    }
    return status;
}
于 2008-08-06T15:18:18.957 回答
1

一个简单的空格字符串分词器应该可以工作,但实际上有很多方法可以做到这一点。

下面是一个使用分词器的例子:

String command = "kick person";
StringTokenizer tokens = new StringTokenizer(command);
String action = null;

if (tokens.hasMoreTokens()) {
    action = tokens.nextToken();
}

if (action != null) {
    doCommand(action, tokens);
}

然后令牌可以进一步用于参数。这一切都假设参数中没有使用空格......所以你可能想要滚动你自己的简单解析机制(比如获取第一个空格并使用之前的文本作为操作,或者如果你不介意使用正则表达式速度命中),只需将其抽象出来,以便可以在任何地方使用。

于 2008-08-05T23:57:02.577 回答
1

当命令的分隔符字符串总是相同的字符串或字符(如“;”)时,建议您使用 StrinkTokenizer 类:

字符串标记器

但是当分隔符变化或复杂时,建议您使用正则表达式,String 类本身可以使用它,方法 split,从 1.4 开始。它使用 java.util.regex 包中的 Pattern 类

图案

于 2008-08-06T15:40:46.917 回答
1

如果语言很简单,就像

动词名词

然后用手拆分效果很好。

如果它更复杂,您应该真正研究像 ANTLR 或 JavaCC 这样的工具。

我在http://javadude.com/articles/antlrtut有一个关于 ANTLR (v2) 的教程,它将让您了解它是如何工作的。

于 2008-09-16T15:35:53.000 回答
1

JCommander看起来相当不错,虽然我还没有测试它。

于 2010-08-20T13:59:05.463 回答
1

如果您的文本包含一些分隔符,那么您可以使用您的split方法。
如果文本包含不规则字符串意味着其中的格式不同,那么您必须使用regular expressions.

于 2012-11-24T09:17:03.450 回答
1

split 方法可以将字符串拆分成指定子字符串表达式的数组regex。它的参数有两种形式,分别是:split( String regex)和split( String regex, int limit),其中split( String regex)实际上是通过调用split(String regex, int limit)来实现的,limit是0。那么,当limit>0limit<0分别代表什么?

jdk时解释:当limit >0时子数组的长度达到limit,即如果可能的话,可以将limit-1细分,剩余为一个子串(除了被limit-1次的字符有字符串拆分结束) ;

limit <0表示对数组的长度没有限制;

limit = 0字符串结尾的空字符串将被截断。 StringTokenizerclass 是出于兼容性原因,保留了遗留类,所以我们应该尝试使用 String 类的 split 方法。参考链接

于 2014-05-13T14:13:15.043 回答