我正在尝试从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
我的正则表达式应该给我tableX
和tableY
,因为它们以数据库名称为前缀。
这是我的表达:
(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_$#-]+)*
答案 0 :(得分:1)
一步一步:
我不知道你为什么要在比赛结束时提出这个预测。我不认为你需要它,所以我把它删除了。
现在我们解决您已指出的问题。问题是在您的数据库名称中匹配[\sa-zA-Z0-9_$#-]*
,您将空格作为有效字符包含在内。我也删除了它。
这是预期的结果吗?
答案 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这样做。正则表达式有其局限性。