仅当字符串中的单词不存在时才匹配字符串

时间:2013-02-25 23:32:09

标签: c# sql regex negative-lookbehind

我正在尝试从SQL脚本中提取表名。我有以下字符串:

from db1.tableX tbx1 --quantity table
inner join tableY tbx2  on tbx1.xyz=tbx2.xyz

我不想匹配此字符串,因为tabley没有数据库名称的前缀。我试图这样做的方法是在数据库名称之前检测字符串中的“on”一词。

我的正则表达式匹配tablex但也匹配tbx1,我不希望我的表达式匹配。

我希望它只在这种情况下匹配。

from db1.tableX tbx1 --quantity table
inner join db1.tableY tbx2 on tbx1.xyz = tbx2.xyz

我的正则表达式应该给我tableXtableY,因为它们以数据库名称为前缀。

这是我的表达:

(insert\s+into|from|inner\s+join|left\s+outer\s+join|join)\s+[\sa-zA-Z0-9_$#-]*\.\s*(?<table>[a-zA-Z0-9_]+)(?=\s+[a-zA-Z0-9_$#-]+)*

2 个答案:

答案 0 :(得分:1)

一步一步:

1)http://regexr.com?33tto

我不知道你为什么要在比赛结束时提出这个预测。我不认为你需要它,所以我把它删除了。

2)http://regexr.com?33ttr

现在我们解决您已指出的问题。问题是在您的数据库名称中匹配[\sa-zA-Z0-9_$#-]*,您将空格作为有效字符包含在内。我也删除了它。

3)http://regexr.com?33ttu

这是预期的结果吗?

答案 1 :(得分:1)

您可以简化表达

(?<=\b(from|join)\s+[a-zA-Z0-9_$#-]*\.\s*)[a-zA-Z0-9_]+

它将直接生成表名,而不必使用命名组。我正在使用模式

(?<=prefix)find

这只返回“find”部分作为匹配值。作为前缀,我使用“from”或“join”,后跟数据库名称点和可能的空格。

\b是单词的开头或结尾。

最后一部分[a-zA-Z0-9_]+是表名。

无论你有内连接,外连接等都没有区别,所以我放弃了这个区别。

评论难以察觉,因为它们可以包含任何内容,并且可以随处出现。您还有两种类型的评论-- Until end of line\* ... *\

你可以尝试检测这样的评论和空格

(\s|--.*?$|\\\*.*?\*\\)+

请注意,退格和星标必须进行转义,因此\*变为\\\**\变为\*\\

$表示行尾。 ?之后的.*可确保不会同时跳过多个注释,从而跳过它们之间的有意义文本。

这在大多数情况下都有效;但是,像结构这样的注释可以包含在字符串文字中:SELECT 'hello -- world' AS greeting FROM ...。这不是评论!如果没有SQL文本的完整语法分析,您将无法涵盖所有​​可能的情况。但你不能用Regex这样做。正则表达式有其局限性。