【问题标题】:Regex to match SUBSTR function with trailing IN clause正则表达式将 SUBSTR 函数与尾随 IN 子句匹配
【发布时间】:2022-01-18 14:47:37
【问题描述】:

我正在使用 PHP preg_match_all() 在 SQL 查询的 WHERE 子句中查找 SUBSTR() 函数调用。匹配应返回包括参数的函数调用以及比较运算符和比较值。示例:

SUBSTR(d.chassinummer, 7, 2) = 'CD'

在查询字符串中,来自SUBSTR() 的结果使用相等运算符或IN() 运算符进行比较。在任何查询中,通常都会有这两者的多种组合和混合组合。示例查询可能如下所示

SELECT * 
FROM tbl 
WHERE col_a = 'abc' 
AND SUBSTR(col_b, 7, 2) = 'cd' 
AND col_c LIKE 'ACD0%' 
AND SUBSTR(col_d, 10, 1) IN ('A','B','C') 
AND SUBSTR(col_e, 5, 3) = 'cde' 
AND SUBSTR(col_f, 2, 1) IN ('C','D','E')

注意:我匹配的查询字符串中没有换行符。

我设法编写了一个几乎可以捕捉到使用等于运算符的情况的模式。看起来是这样的

preg_match_all('/substr\(.*?\) *?= *?\'.*?\'/i', $query, $matches);

但是,在给定的示例查询中,我的模式因终止匹配而失败,其中IN() 出现在以后的匹配中。在摆弄了一段时间后,我投降并寻求专家的支持。谁能帮我理解如何从给定的示例查询中提取以下匹配项

  1. SUBSTR(col_b, 7, 2) = 'cd'
  2. SUBSTR(col_d, 10, 1) IN ('A','B','C')
  3. SUBSTR(col_e, 5, 3) = 'cde'
  4. SUBSTR(col_f, 2, 1) IN ('C','D','E')

如果将其分成两个单独的模式并使用两个 preg_match_all() 调用更容易,我觉得很好,但是如果可以在一个调用中完成,那会感觉更干净。

非常感谢。

【问题讨论】:

  • 对于示例,您可以尝试使用 substr\([^()]*\)\h*(?:=\h*'[^']*'|IN\h*\([^()]*\)) regex101.com/r/zv5b9C/1 但它不会考虑嵌套查询。
  • 试试这个正则表达式/substr\(.*?\)*?(:?\=|IN)*?(:?\'|\().*(:?\'|\))/giregex101.com/r/y9f52A/1

标签: php regex


【解决方案1】:

对于示例数据(不考虑嵌套查询),您可以使用:

substr\([^()]*\)\h*(?:=\h*'[^']*'|IN\h*\([^()]*\))

模式匹配:

  • substr\([^()]*\)
  • \h* 匹配可选空格
  • (?:非捕获组
    • =\h*'[^']*' 匹配 = 然后是可选空格,从 '' 之间不匹配 '
    • |或者
    • IN\h*\([^()]*\) 匹配 IN 然后是可选空格,从 () 不匹配 () 之间
  • )关闭非捕获组

Regex demo | PHP demo

例子

$re = '`substr\([^()]*\)\h*(?:=\h*\'[^\']*\'|IN\h*\([^()]*\))`mi';
$str = <<<STR
SELECT * 
FROM tbl 
WHERE col_a = 'abc' 
AND SUBSTR(col_b, 7, 2) = 'cd' 
AND col_c LIKE 'ACD0%' 
AND SUBSTR(col_d, 10, 1) IN ('A','B','C') 
AND SUBSTR(col_e, 5, 3) = 'cde' 
AND SUBSTR(col_f, 2, 1) IN ('C','D','E')
STR;

preg_match_all($re, $str, $matches, 0);

print_r($matches[0]);

输出

Array
(
    [0] => SUBSTR(col_b, 7, 2) = 'cd'
    [1] => SUBSTR(col_d, 10, 1) IN ('A','B','C')
    [2] => SUBSTR(col_e, 5, 3) = 'cde'
    [3] => SUBSTR(col_f, 2, 1) IN ('C','D','E')
)

【讨论】:

  • 谢谢!似乎对我的查询集合很有效。写得很好的答案,太棒了!我会剖析它并学习=D
猜你喜欢
  • 1970-01-01
  • 2013-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多