我有一个IronPython脚本,它针对SQL Server数据库执行一堆SQL语句.语句是大字符串,实际上包含多个语句,由"GO"关键字分隔.当它们从sql管理工作室和其他一些工具运行时可以工作,但不能在ADO中运行.所以我使用2.5"re"模块拆分字符串,如下所示:
splitter = re.compile(r'\bGO\b', re.IGNORECASE)
for script in splitter.split(scriptBlob):
if(script):
[... execute the query ...]
Run Code Online (Sandbox Code Playgroud)
在罕见的情况下,这会打破注释或字符串中的单词"go".如何解决这个问题?即正确地将此字符串解析为两个脚本:
-- this is a great database script! go team go!
INSERT INTO myTable(stringColumn) VALUES ('go away!')
/*
here are some comments that go with this script.
*/
GO
INSERT INTO myTable(stringColumn) VALUES ('this is the next script')
Run Code Online (Sandbox Code Playgroud)
编辑:
我搜索了更多,发现了这个SQL文档:http: //msdn.microsoft.com/en-us/library/ms188037(SQL.90).aspx
事实证明,GO必须按照自己的方式提出一些答案.然而,它后面可以跟一个"count"整数,它实际上会多次执行语句批处理(之前有人实际使用过它),然后可以在同一行上单行注释(但不是多行,我测试了这个.)所以神奇的正则表达式看起来像:
"(?m)^\s*GO\s*\d*\s*$"
Run Code Online (Sandbox Code Playgroud)
除此之外不考虑:
"--"
后跟换行符之外的任何字符).我不关心捕获"计数"参数并使用它.现在我有一些技术文档,我非常接近写这个"规范",而且再也不用担心了.
因为你可以在注释,嵌套注释,查询中的注释等内部发表评论,所以没有理智的方法来使用正则表达式.
只需想象一下以下脚本:
INSERT INTO table (name) VALUES (
-- GO NOW GO
'GO to GO /* GO */ GO' +
/* some comment 'go go go'
-- */ 'GO GO' /*
GO */
)
Run Code Online (Sandbox Code Playgroud)
没有提到:
INSERT INTO table (go) values ('xxx') GO
Run Code Online (Sandbox Code Playgroud)
唯一的方法是构建一个有状态的解析器.一次读取一个char,并且有一个标志,当它在注释/引用分隔的字符串/ etc中时将被设置,并在结束时重置,因此代码可以忽略"GO"实例.
如果GO总是在一条线上,你可以像这样使用split:
#!/usr/bin/python
import re
sql = """-- this is a great database script! go team go!
INSERT INTO myTable(stringColumn) VALUES ('go away!')
/*
here are some comments that go with this script.
*/
GO 5 --this is a test
INSERT INTO myTable(stringColumn) VALUES ('this is the next script')"""
statements = re.split("(?m)^\s*GO\s*(?:[0-9]+)?\s*(?:--.*)?$", sql)
for statement in statements:
print "the statement is\n%s\n" % (statement)
Run Code Online (Sandbox Code Playgroud)
(?m)
开启多行匹配数,也就是^
和$
将匹配开始和线路的端部(而不是启动和字符串的末尾).^
在一行的开头匹配\s*
匹配零个或多个空格(空格,制表符等)GO
匹配文字GO\s*
和之前一样(?:[0-9]+)?
匹配可选的整数(可能的前导零)\s*
和之前一样(?:--.*)?
匹配可选的行尾注释 $
匹配在一行的末尾拆分将消耗GO线,因此您不必担心它.这将为您提供一份陈述清单.
这个修改后的拆分有一个问题:在GO之后它不会给你回数,如果这很重要我会说是时候转移到某种形式的解析器了.