Java命名的反向引用不匹配

时间:2014-03-22 21:25:24

标签: java sql regex parsing backreference

我正在编写一个简化的SQL解析器,它使用正则表达式匹配每个有效命令。我坚持匹配以下内容:

attribute1 type1,attribute2 type2,attribute3 type3,...

其中属性是表列的名称,类型可以是CHAR(大小),INT或DEC。这在CREATE TABLE语句中使用:

CREATE TABLE student (id INT, name CHAR(20), gpa DEC);

要调试它,我试图匹配它:

id INT, name CHAR(20), gpa DEC

用这个:

(?<attributepair>[A-Za-z0-9_]+ (INT|(CHAR\([0-9]{1,3}\))|DEC))(, \k<attributepair>)*

我甚至在没有命名反向引用的情况下尝试过它:

([A-Za-z0-9_]+ (INT|(CHAR\([0-9]{1,3}\))|DEC))(, \1)*

我用regexpal测试了后一个正则表达式并且它匹配,但是当我在我的Java程序中尝试时它们都没有。有什么我想念的吗?我怎样才能做到这一点?也许这与我如何调用Pattern.compile()有关,就像我错过了一个标志一样。我也有JDK v7。

更新:我发现虽然matches()返回false,但lookingAt()和find()返回true。它匹配每个单独的属性。我想制作我的正则表达式,因此它匹配整个表达式而不是每个属性。

2 个答案:

答案 0 :(得分:0)

当您执行([A-Za-z0-9_]+ (INT|(CHAR\([0-9]{1,3}\))|DEC))(, \1)*之类的操作时,后向引用是针对第一组实际匹配的内容。

即,id INT, id INT, name CHAR(20), gpa DECid INT, id INT将成为同一场比赛的一部分的意义上适用于反向引用。 (如果你坚持使用regexpal,你会根据亮点清楚地看到差异。)

答案 1 :(得分:0)

Java 中没有“匹配尽可能多的时间并将所有组合在一起”
你要么必须自己使用:

while(matcher.find()) {
    // ...
}

...或者使用已经匹配find的单个调用中的所有内容的正则表达式。


例如,您可以尝试使用以下正则表达式(如Java String ),它将同时匹配您的所有属性。

(?:\\w+ (?:INT|CHAR(?:\\(\\d{1,3}\\))?|DEC)(?:, )?)+

这是一个有效的例子:

final String str = "CREATE TABLE student (id INT, name CHAR(20), gpa DEC);";
final Pattern p = Pattern.compile("(?:\\w+ (?:INT|CHAR(?:\\(\\d{1,3}\\))?|DEC)(?:, )?)+");
final Matcher m = p.matcher(str);
if(m.find()) {
    System.out.println(m.group());  // prints "id INT, name CHAR(20), gpa DEC"
};

输出:

id INT, name CHAR(20), gpa DEC