SQL 查询的正则表达式给出了一个空的 MatchCollection

Posted

技术标签:

【中文标题】SQL 查询的正则表达式给出了一个空的 MatchCollection【英文标题】:Regex for SQL query gives an empty MatchCollection 【发布时间】:2010-09-22 12:18:32 【问题描述】:

我尽量保持简洁。我必须编写一个以 SQL 形式进行查询并搜索 XML 的程序。现在我正在尝试将字符串分解成逻辑片段,以便我可以使用它们。我有一个字符串作为输入,并希望得到一个 MatchCollection 作为输出。

请注意,下面的测试字符串是我强加给用户的特殊格式,以保持简单。每行只允许一个语句,并且排除嵌套查询-

string testString = "select apples \n from dblp \r where we ate \n group by all them \r HAVING NO SHAME \n";

我使用正则表达式的模式如下:

Regex reg = new Regex(@"(?<select> \A\bselect\b .)" +  
                      @"(?<from> ^\bfrom\b .)" +
                      @"(?<where> ^\bwhere\b .)" +
                      @"(?<groupBy> ^\bgroup by\b .)" +
                      @"(?<having> ^\bhaving\b .)"
                      , RegexOptions.IgnoreCase | RegexOptions.Multiline
                      );

据我所知,这应该给我匹配每个组的测试字符串。我会在每一行的开头寻找“select”的完全匹配,然后是除换行符以外的任何字符。

现在我创建集合:

MatchCollection matches = reg.Matches(testString);

为了确保它有效,我使用了一个 foreach 并打印了以下匹配项:

foreach(Match match in matches)

    Console.WriteLine("Select: 0", match.Groups["select"]);
   //and so on

问题是集合总是空的。某个地方的正则表达式一定有缺陷,但我太缺乏经验,无法找到它。你能帮帮我吗?非常感谢!


我尝试使用 .* 而不是 .直到我被告知。甚至会数学多个字符。我毫不怀疑这可能是个问题,但即使更换它我也没有得到任何结果。

我不明白为什么在正则表达式找到换行符之前匹配以定义的单词开头并附加任何字符的行是如此困难。在我看来,这应该是一个相对容易的任务。

【问题讨论】:

【参考方案1】:

我认为您需要明确匹配行终止符,并按照其他人的建议更好地处理空格。假设用户可以在 \r 和 \n 之间进行选择,请尝试

@"(?<select>\Aselect .+)[\n\r]" +
@"(?<from>\s*from .+)[\n\r]" +
@"(?<where>\s*where .+)[\n\r]" +
@"(?<groupBy>\s*group by .+)[\n\r]" +
@"(?<having>\s*having .+)[\n\r]"

只要您使用正则表达式,您可能希望做得更好:

@"\Aselect (?<select>.+)[\n\r]" +
@"\s*from (?<from>.+)[\n\r]" +
@"\s*where (?<where>.+)[\n\r]" +
@"\s*group by (?<groupBy>.+)[\n\r]" +
@"\s*having (?<having>.+)[\n\r]"

我对这种使用的正则表达式最大的问题是,你能给出的唯一错误信息是事情失败了。您不能向用户提供有关他们做错了什么的更多信息。

【讨论】:

【参考方案2】:

换行符匹配可能有问题:是 LF(Unix 标准)、CR(MacOS)还是 CR LF(Windows)?如果你不知道,也许你应该匹配它:[\n\r]+

编辑:您在测试字符串中包含了一些空格,围绕着换行符,您在 rexex 中没有考虑到这些空格。

(?<from>^\s*from\b.*[\n\r]+$)

【讨论】:

【参考方案3】:

正如您所说,匹配关键字然后使用 (.+) 匹配该行的其余部分很容易。但是你必须匹配所有中间的字符,而你没有这样做。 (^ 行锚点与行分隔符之后的位置相匹配,而不是分隔符本身。)您可以使用 \s+ 来使用行分隔符以及下一行的任何前导空格。

@"select\s+(?<select>.+)\s+" +
@"from\s+(?<from>.+)\s+" +
@"where\s+(?<where>.+)\s+" +
@"group by\s+(?<groupBy>.+)\s+" +
@"having\s+(?<having>.+)";

我还重新安排了一些事情,以便不捕获 SQL 关键字;这似乎是多余的,因为您使用的是命名组。

【讨论】:

【参考方案4】:

我没有尝试为您构建一个有效的正则表达式,但我可以看到几个问题。其他人指出了前两个问题,但没有指出第三个问题。

    您不能使用单个点来匹配可变部分,例如“apples”。试试 \w+ 或 \S+ 您的字符串已嵌入换行符。您需要将那些与 [\r\n]+ 或 \s+ 匹配 .NET 正则表达式引擎将 \n 视为换行符,但不是 \r 或 \r\n。因此,^ 将在 \n 之后匹配,而不是在 \r 之后。如果您执行第 2 步,则无论如何都不需要锚点,因此请移除它们。

【讨论】:

以上是关于SQL 查询的正则表达式给出了一个空的 MatchCollection的主要内容,如果未能解决你的问题,请参考以下文章

使用php preg_match(正则表达式)将camelCase单词拆分为单词

oracle10g中,如何查询正则表达式匹配指定字符串的匹配个数?

sql server中对字段使用正则表达式替换???

SQL正则表达式检查JSON数组中是否存在至少一个项目

python正则表达式模块re简介

python基础入门