单独的正则表达式匹配,但它们的联合不匹配

时间:2012-05-11 14:59:49

标签: java regex string

出于学术目的,我们的基本团队(我和朋友)正在用java编写基于磁贴的游戏。为了使用这些图块,我们已经给出了一个配置文件,其中包含套牌中所有图块的字符串表示,每行一次。以下是一些例子:

N=N S=C O=C E=N NS=0 NE=0 NO=0 OE=0 SE=0 SO=1
N=S S=S O=S E=S NS=0 NE=0 NO=0 OE=0 SE=0 SO=0

在上面的表示中,N,S,O和E映射到北,南,东和西的基点,而前四个任务的右成员映射到道路(S),城市(C)和场(N)。以下六组表示是否存在两点之间的链接。例如,SO = 1表示南和西联系。

我们的第一个想法是使用标准Java库提供的Pattern类,用正则表达式解析这些行。我的队友编写了一个代码来为整个字符串生成一个Pattern,汇集较小的模式来指示一些枚举的可能值(以前的Position包含基本点,AssetType包含像road或city这样的结构)。我不会粘贴代码的代码,因为它非常耗费空间而且不是很优雅。但是,我可以告诉你它是正确的。

在继续之前,我想指出实际上是瓦片串组成的两个主要部分:边界规范(即前4个分配)和链接规范(最后6个)。因此,我们有两个解析器。第一个能够解析诸如“N = N S = C O = C E = N”的字符串,并且第二个“NS = 0 NE = 0 NO = 0 OE = 0 SE = 0 SO = 1”。他们的模式是正确的。我们对它们进行了全面测试,所有测试顺利通过。

现在来了。因为tile字符串总是由第一部分和第二部分组成,所以我们为整个字符串创建了模式,只是为第一部分添加模式,而为第二部分添加模式,用\ s +分隔它们并围绕它们各自与parantheses。结果表达式如下:

(N\s*\=\s*(N|S|C)(,(R|B|V|G|N))?\s+S\s*\=\s*(N|S|C)(,(R|B|V|G|N))?\s+O\s*\=\s*(N|S|C)(,(R|B|V|G|N))?\s+E\s*\=\s*(N|S|C)(,(R|B|V|G|N))?)\s+(NS\s*\=\s*(0|1)\s+NE\s*\=\s*(0|1)\s+NO\s*\=\s*(0|1)\s+OE\s*\=\s*(0|1)\s+SE\s*\=\s*(0|1)\s+SO\s*\=\s*(0|1))

我知道它看起来很糟糕,但它是一个编译时的结果。尽管如此,我们还是针对某些字符串测试了它,就像我上面发布的字符串一样,只是发现它不匹配,尽管单个模式匹配。 我们试图在一个在线模拟器上运行它,比如this,它完美匹配。我们不知道如何使它匹配。有什么想法吗?

一些代码:

public Tile from(String tileString) {
    Matcher matcher = pattern.matcher(tileString);

    return new InnerTile(
            tileBorderBuilder.from(matcher.group(1)),
            tileLinkageBuilder.from(matcher.group(14)));
}

tileBorderBuilder.from解析第一部分并返回TileBorder对象。 tileLinkageBuilder.from执行相同的操作并返回TileLinkage对象。它引发了一个例外:“找不到匹配”。

P.S。:我们使用的是Java SE 1.6或Open-JDK6(它们都失败了。)

1 个答案:

答案 0 :(得分:0)

要调试这样的问题,请从更简单的正则表达式开始,然后从那里构建,即尝试匹配

 N=N
 N=N S=C
 ...
 N=N S=C O=C E=N NS=0 NE=0 NO=0 OE=0 SE=0 SO=1

(相应地缩短正则表达式)。这将帮助您确定出现问题的正则表达式中的位置。

那就是说,我建议用这个正则表达式解析配置:

\s*([^\s=]+)\s*=\s*(\S)

将输入拆分为行,然后将其重复应用于每一行以读取每个“单词”。

这是Java方面的更多努力,但它可以控制正则表达式并使您的代码易于阅读,理解和扩展......因为在几天内,您将要添加另一个磁贴或新选项 - 一个月后,正则表达式将控制你的生活。