【问题标题】:Why does a python regex only work with capturing brackets?为什么 python 正则表达式仅适用于捕获括号?
【发布时间】:2012-08-12 20:16:12
【问题描述】:

我正在编写一个 python 函数来处理多行 SQL 语句。

例如

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)

它可以正常工作,但前提是我将.*? 术语括在括号中,这样它就变成了(.*?)。如果我不这样做,那么我什么都不匹配。

这是为什么?提前致谢。

【问题讨论】:

  • 你能把你的代码贴在你使用 sql_line 进行匹配的那一行吗?
  • @Dmitry:发布为上面的编辑。

标签: python mysql regex


【解决方案1】:

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

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

由于永远不应该匹配,因此第一个捕获组在成功匹配时将始终为空。因为像.findall 这样的一些方法只会返回捕获组(如果它们存在的话),你只会看到一个空字符串列表。

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

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

【讨论】:

  • 我喜欢 [^;] 的建议,因为我的大脑需要一分钟来计算。谢谢
【解决方案2】:

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

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

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

【讨论】:

  • 谢谢 - 这是有道理的。我把括号包括在内是因为我认为它们对于交替是必要的——我想不是。不知道多线的事情。感谢您花时间回答这个问题。关于 Stackoverflow 的第一个问题。对快速反应感到惊讶。谢谢
  • @drstevok:即使在需要分组的情况下,您也可以使用(?:...) 而不是(...) 以避免捕获。
猜你喜欢
  • 2015-01-20
  • 2013-10-31
  • 1970-01-01
  • 1970-01-01
  • 2011-08-26
  • 2012-04-13
  • 1970-01-01
  • 1970-01-01
  • 2017-03-23
相关资源
最近更新 更多