【问题标题】:Java named backreferences not matchingJava 命名反向引用不匹配
【发布时间】:2014-03-22 21:25:23
【问题描述】:

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

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

其中属性是表列的名称,类型可以是 CHAR(size)、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 测试了后一个 regex 表达式并且它匹配,但是当我在我的 Java 程序中尝试它时两者都没有。有什么我想念的吗?我怎样才能使这项工作?也许这与我调用 Pattern.compile() 的方式有关,就像我是否缺少标志一样。我也有 JDK v7。

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

【问题讨论】:

    标签: java sql regex parsing backreference


    【解决方案1】:

    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
    

    【讨论】:

      【解决方案2】:

      当您执行([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 将成为同一匹配的一部分。 (如果你把它放在正则表达式中,你会根据突出显示非常清楚地看到差异。)

      【讨论】:

        猜你喜欢
        • 2015-09-03
        • 2021-12-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-26
        相关资源
        最近更新 更多