正则表达式匹配字符串不在括号内

时间:2019-01-04 00:51:59

标签: javascript regex string

我一直在努力寻找一个正则表达式,仅当它们不在括号内时才帮助我匹配3个不同的字符串,但是到目前为止,我仅设法将其匹配在括号旁边,并且在这种特定情况下不适合我。

为澄清起见,我需要匹配任何括号中都不包含的字符串“ HAVING”,“ ORDER BY”和“ GROUP BY”,无论括号中包含的字符串不仅仅是字符串。

在这种情况下:

Select *
from some_table
group by something;

应该匹配,但是:

Select *
from(
   Select *
   from some_other_table
   group by something_else
)

Select this, and_this
from(
   Select *
   from some_other_table
   having some_condition
)

不应该。

我不是Javascript正则表达式的专家,因此,您能给我的任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

我假设您想检查给定的SQL查询是否在顶层(不在子查询中)包含HAVINGORDER BYGROUP BY

由于括号和单词都可以包含在字符串文字('...'),带引号的标识符("...")和注释(-- ...)中,这使情况变得复杂。 / p>

在下面的代码中,我假设这就是所有可能“出错”的东西(即没有其他引用结构),并且没有带引号的字符是特殊的(特别是,\的使用没有区别)

想法:

  • 删除所有引用的构造,例如字符串文字和注释。
  • 删除所有带括号的组。
  • 检查关键字的其余字符串。

“删除”一词的意思是“用空格代替”,因为否则可能会在以前没有的地方创建新令牌(例如,hav(...)IN"asdf"g会变成havINg,如果用括号/引用的部分被替换为空)。

实施:

function contains_groupy_bits(sql) {
    sql = sql.replace(/'[^']*'|"[^"]*"|--[^\n]*/g, ' ');
    let tmp;
    while ((tmp = sql.replace(/\([^()]*\)/g, ' ')) !== sql) {
        sql = tmp;
    }
    return /\b(?:having|order\s+by|group\s+by)\b/i.test(sql);
}

const examples = [
    `Select *
    from some_table
    group by something;`,

    `Select *
    from(
       Select *
       from some_other_table
       group by something_else
    )`,

    `Select this, and_this
    from(
       Select *
       from some_other_table
       having some_condition
    )`,

    `select name, count(*) from things
    where mark = '('
    group by name -- )`,
];

for (const ex of examples) {
    console.log("'" + ex + "': " + contains_groupy_bits(ex));
}