我正在编写一个python函数来处理多行SQL语句。
e.g。
multi_stmt = """
-- delete empty responses
DELETE FROM idlongDVR_responses WHERE new_response_code = '';
DELETE FROM idwideDVR_responses WHERE new_response_code = '';
-- create a current responses table for idlongDVR
DROP TABLE IF EXISTS idlongDVR_respCurr;
CREATE TABLE idlongDVR_respCurr
SELECT *, MAX(modifiedat) AS latest FROM idlongDVR_responses
GROUP BY sitecode, id, dass, tass, field, value, validation_message
ORDER BY sitecode, id, dass, tass; """
所以我写了一个正则表达式来识别换行符,如果它后面没有双连字符(开始注释),并以分号结尾
sql_line = re.compile(r"""
\n+ # starting from a new line sequence
(?!(--|\n)) # if not followed by a comment start "--" or newline
(.*?) # <<<<< WHY ARE THESE CAPTURING BRACKETS NEEDED?
; # ending with a semicolon
""", re.DOTALL|re.VERBOSE|re.MULTILINE)
stmts = sql_line.findall(multi_statement)
for stmt in stmts:
stmt = stmt[1]
if len(stmt) > 0:
cursor.execute(stmt)
它工作正常,但只有当我将.*?
术语括在括号中才会变为(.*?)
。如果我不这样做,那么我什么都不匹配。
这是为什么?提前谢谢。
答案 0 :(得分:2)
“需要使用这些捕获括号”,因为您在负向前瞻中使用了捕获支架。
(?!(--|\n))
^ ^
由于永远不会匹配,因此第一个捕获组在成功匹配时将始终为空。由于某些方法(如.findall
)只返回捕获组(如果存在),因此您只会看到空字符串列表。
在此处删除(
... )
应该使正则表达式符合您的预期。顺便说一句,您可以使用[^;]*
代替.*?
。
sql_line = re.compile(r"\n+(?!--|\n)[^;]*;")
答案 1 :(得分:0)
你正在使用findall
,不是吗? findall
很奇怪。如果正则表达式中有任何捕获组,则仅返回 捕获组的内容。正如@KennyTM指出的那样,你的前瞻中有一个捕获组,因为它是否定预测,所以只有当组无法捕获任何内容时,你的整体匹配才会成功。因此,您的空字符串列表。
当你使用.*?
周围的括号时,不要问我为什么那些空组不会出现。通过阅读文档,我希望它返回一个由两个组组成的元组列表:一个是空的,一个是你期望的匹配。但我只得到非空组。这似乎是findall
的另一层荒谬,我之前没有遇到过。
顺便说一句,您不需要MULTILINE
标志。所做的就是改变锚点^
和$
的行为,允许它们在行边界以及整个字符串的开头和结尾处匹配。也许你已经知道了,但是有一个非常持久的流氓模因,“如果它是多线的,你必须使用MULTILINE
”,并且每当我看到它时我会试着加盖它。