为什么python正则表达式只适用于捕获括号?

时间:2012-08-12 20:16:13

标签: python mysql regex

我正在编写一个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)

它工作正常,但只有当我将.*?术语括在括号中才会变为(.*?)。如果我不这样做,那么我什么都不匹配。

这是为什么?提前谢谢。

2 个答案:

答案 0 :(得分:2)

“需要使用这些捕获括号”,因为您在负向前瞻中使用了捕获支架。

(?!(--|\n))
   ^     ^

由于永远不会匹配,因此第一个捕获组在成功匹配时将始终为空。由于某些方法(如.findall)只返回捕获组(如果存在),因此您只会看到空字符串列表。

在此处删除( ... )应该使正则表达式符合您的预期。顺便说一句,您可以使用[^;]*代替.*?

sql_line = re.compile(r"\n+(?!--|\n)[^;]*;")

答案 1 :(得分:0)

你正在使用findall,不是吗? findall很奇怪。如果正则表达式中有任何捕获组,则仅返回 捕获组的内容。正如@KennyTM指出的那样,你的前瞻中有一个捕获组,因为它是否定预测,所以只有当组无法捕获任何内容时,你的整体匹配才会成功。因此,您的空字符串列表。

当你使用.*?周围的括号时,不要问我为什么那些空组不会出现。通过阅读文档,我希望它返回一个由两个组组成的元组列表:一个是空的,一个是你期望的匹配。但我只得到非空组。这似乎是findall的另一层荒谬,我之前没有遇到过。

顺便说一句,您不需要MULTILINE标志。所做的就是改变锚点^$的行为,允许它们在行边界以及整个字符串的开头和结尾处匹配。也许你已经知道了,但是有一个非常持久的流氓模因,“如果它是多线的,你必须使用MULTILINE”,并且每当我看到它时我会试着加盖它。