我正在编写一个简化的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。它匹配每个单独的属性。我想制作我的正则表达式,因此它匹配整个表达式而不是每个属性。
答案 0 :(得分:0)
当您执行([A-Za-z0-9_]+ (INT|(CHAR\([0-9]{1,3}\))|DEC))(, \1)*
之类的操作时,后向引用是针对第一组实际匹配的内容。
即,id INT, id INT, name CHAR(20), gpa DEC
在id 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