正则表达式匹配特定表的复杂 Where 子句
Posted
技术标签:
【中文标题】正则表达式匹配特定表的复杂 Where 子句【英文标题】:Regex to Match Complex Where Clause for Certian Table 【发布时间】:2018-10-11 13:04:47 【问题描述】:我有一个程序,它采用受限制的 SQL Server WHERE 子句并删除以 certian 表为目标的 sectiona。这种 where 子句的一个例子是
AND (Util.Source='IP%' AND Util.ReqType = 'IP') AND (Util.Epinum 为空) AND ([Episode].[YN] = 'Y')
我需要删除使用表Episode
的所有查询部分,并考虑(
、)
来括起语句以及字段名称的方括号等。所以要做到这一点我有
private string BuildResourceWhereClauses(string whereClauses, string episodeTable)
Regex r = new Regex(
$"AND\\s+\\(*\\[*episodeTable\\]*\\.\\[*\\w+\\]*\\s*(=|<>|<=|>=)(\\s*\\'*(NULL|\\S+|\\((.*?)\\)+)\\'*\\s*\\)*)1",
RegexOptions.IgnoreCase);
string tmp = r.Replace(whereClauses, String.Empty).Trim();
return $" tmp";
这很好,返回
AND (Util.Source='IP%' AND Util.ReqType = 'IP') AND (Util.Epinum 为空)
但是现在,我被要求扩展它,以便我们允许所有 SQL WHERE 子句语法。所以我们现在可以有一个类似
的 where 子句AND (Util.Source='IP%' AND Util.ReqType = 'IP') AND (Util.Epinum 为空) AND ([Episode].[YN] = 'Y') AND (Episode.Paste = 'Y') AND [Episode].[Source] = '%6' AND [Episode].[TFC] NOT IN ('LWC', 'POD')
说我们要“解析”,所以我把上面的方法修改为
private string BuildResourceWhereClauses(string whereClauses, string episodeTable)
Regex r = new Regex(
$"AND\\s+\\(*\\[*episodeTable\\]*\\.\\[*\\w+\\]*\\s*(=|<>|<=|>=|LIKE|IN|NOT IN|IS|BETWEEN\\s+\\w+\\s+AND)(\\s*\\'*(NULL|\\S+|\\((.*?)\\)+)\\'*\\s*\\)*)1",
RegexOptions.IgnoreCase);
string tmp = r.Replace(whereClauses, String.Empty).Trim();
return $" tmp";
使用episodeTable = "Episode"
我得到回报
AND (Util.Source='IP%' AND Util.ReqType = 'IP') AND (Util.Epinum 为空)'POD')
此缺失匹配 AND (Episode.Paste = 'Y')
、AND [Episode].[Source] = '%6'
和 AND [Episode].[TFC] NOT IN ('LWC', 'POD')
。
正则表达式有什么问题,如何修改它以返回我想要的?
与其让这个正则表达式变得复杂,我们可以简化它吗?
感谢您的宝贵时间。
下面的答案去掉了我之前拥有的一些功能(我的错是没有规定我需要保留它!以及是什么让这变得如此困难 - 捕获所有案例“)。所以我需要匹配这个字符串
AND (Util.Source='IP%' AND Util.ReqType = 'IP') AND (Util.Epinum 为空) AND ([Episode].[YN] = 'Y') AND Episode.FRC BETWEEN 10 AND 20 AND Episode.Dt 介于 '2011/02/25' 和 '2011/02/27' 之间 AND (Util.Source='IP%' AND Util.ReqType = 'IP') AND (Util.Epinum 为空) AND ([Episode].[YN] = 'Y' AND Episode.TFC IS NOT LIKE '655r% ') AND (Episode.Paste = 'Y') AND [Episode].[Source] IS NOT LIKE '%6' AND [Episode].[TFC] NOT IN ('LWC', 'POD') AND [Episode].[ TFC] 为空
所以在C#中,我需要下面的代码
string whereClaues =
"AND (Util.Source='IP%' AND Util.ReqType = 'IP') AND (Util.Epinum is null) " +
"AND ([Episode].[YN] = 'Y') AND Episode.FRC BETWEEN 10 AND 20 AND Episode.Dt between '2011/02/25' and '2011/02/27' " +
"AND (Util.Source='IP%' AND Util.ReqType = 'IP') AND (Util.Epinum is null) AND ([Episode].[YN] = 'Y' AND Episode.TFC IS NOT LIKE '655r%') " +
"AND (Episode.Paste = 'Y') AND [Episode].[Source] IS NOT LIKE '%6' AND [Episode].[TFC] NOT IN ('LWC', 'POD') AND [Episode].[TFC] IS NULL";
string tmp = r.Replace(whereClauses, String.Empty).Trim();
给tmp
作为
AND (Util.Source='IP%' AND Util.ReqType = 'IP') AND (Util.Epinum 为空) AND (Util.Source='IP%' AND Util.ReqType = 'IP') AND (Util.Epinum 为空)
删除所有Episode
子句,包括BETWEEN
语句和IS NOT NULL
和IS NULL
语句。
有
AND\s+\(*\[*Episode\]*\.\[*\w+\]*\s*(<>|[><]?=|(?:NOT\s+)?IN|(?:IS\s+)?LIKE|(?:IS\s+NOT\s+)?LIKE|BETWEEN(\s*\'*(\((.*?)\)+|NULL|\S+)\'*\s*\)*)AND)(\s*\'*(\((.*?)\)+|NULL|\S+)\'*\s*\)*)
但这不匹配
Episode.TFC 为空
【问题讨论】:
What is wrong with the regex?
你正在使用正则表达式来修改 SQL,这是一个可怕的 hack。为什么不能只修改 SQL?
SQL 来自用户输入。此 where 子句在一个 CTE 查询中用于创建一个 tmp 表,该表随后与另一个连接。我需要去掉 where 子句的 Episode
部分,以便在后续的连接查询中使用。与所有类似的事情一样,我为什么使用这种方法并不总是很清楚。我在这里使用正则表达式,因为它似乎是一种方便的方式来做我想做的事,而无需编写完整的解析器 - 这将是更多的工作。
试试this one
@WiktorStribiżew 我喜欢这样,请做一个简短的回答,我会接受。我认为这可能会在未来对其他人有所帮助。
附有解释。
【参考方案1】:
看来您可以通过以下方式扩展您的模式:
$@"AND\s+\(*\[*episodeTable\]*\.\[*\w+\]*\s*(<>|[><]?=|(?:NOT\s+)?IN)(\s*\'*(\((.*?)\)+|NULL|\S+)\'*\s*\)*)"
请参阅regex demo here。
详情
AND
- 一个子字符串
\s+
- 1+ 个空格
\(*
- 0+ (
字符
\[*
- 0+ [
字符
Episode
- 表名
\]*
- 0+ ]
字符
\.
- 一个 .
字符
\[*
- 0+ [
字符
\w+
- 1+ 字字符
\]*
- 0+ ]
字符
\s*
- 0+ 个空格
(<>|[><]?=|(?:NOT\s+)?IN)
- 第 1 组:<>
、<=
、>=
、=
、NOT IN
或 IN
(\s*\'*(\((.*?)\)+|NULL|\S+)\'*\s*\)*)
- 第 2 组:
\s*
- 0+ 个空格字符
\'*
- 0+ '
字符
(\((.*?)\)+|NULL|\S+)
- 第 3 组:
\(
- 一个(
(.*?)
- 第 4 组:除换行符之外的任何 0+ 字符尽可能少
\)+
- 1+ )
字符
|
- 或
NULL
- NULL
子字符串
|
- 或
\S+
- 1+ 非空白字符
\'*
- 0+ '
字符
\s*
- 0+ 个空格
\)*
- 0+ )
字符。
【讨论】:
后部疼痛,但我忘记了AND [Episode].[Source] IS LIKE '%6'
和AND [Episode].[Source] IS NOT LIKE '%6'
之类的部分。此外,在第 3 组中,我们可能有 NOT NULL
您能否就我的更新提出建议 AND\s+\(*\[*Episode\]*\.\[*\w+\]*\s*(<>|[><]?=|(?:NOT\s+)?IN|(?:IS\s+)?LIKE)(\s*\'*(\((.*?)\)+|IS\s+(?:NOT\s+)?\s+NULL|\S+)\'*\s*\)*)
我尝试添加对 IS NULL 和 IS NOT NULL 的支持不起作用。以上是关于正则表达式匹配特定表的复杂 Where 子句的主要内容,如果未能解决你的问题,请参考以下文章