如何在Python中将长正则表达式规则拆分为多行

65 投票
6 回答
43755 浏览
提问于 2025-04-17 05:37

这个真的能做到吗?我有一些非常长的正则表达式规则,难以理解,因为它们一次不能在屏幕上全部显示出来。举个例子:

test = re.compile(
    '(?P<full_path>.+):\d+:\s+warning:\s+Member\s+(?P<member_name>.+)\s+\((?P<member_type>%s)\) of (class|group|namespace)\s+(?P<class_name>.+)\s+is not documented'
        % (self.__MEMBER_TYPES),
    re.IGNORECASE)

反斜杠或者三重引号是没用的。

6 个回答

21

使用 re.Xre.VERBOSE 这个标志。除了可以省略引号,这种方法在其他正则表达式的实现中,比如 Perl,也能用。

来自 官方文档

re.X

re.VERBOSE

这个标志让你可以写出更好看、更易读的正则表达式。它允许你把模式的逻辑部分分开,并添加注释。模式中的空格会被忽略,除了在字符类里面或者前面有未转义的反斜杠的情况下。当一行中有一个 # 符号,并且这个 # 不是在字符类里,也没有前面的未转义的反斜杠时,从这个 # 开始到行末的所有字符都会被忽略。

这意味着下面这两个匹配小数的正则表达式对象在功能上是相同的:

a = re.compile(r"""\d +  # the integral part
                   \.    # the decimal point
                   \d *  # some fractional digits""", re.X)
b = re.compile(r"\d+\.\d*")

这对应于内联标志 (?x)


附注:提问者在之前的编辑中提到他们最终使用了这个解决方案

29

根据文档,关于字符串字面量连接的说明:

多个相邻的字符串字面量(用空格分隔),可以使用不同的引号方式,它们的意思和直接连接在一起是一样的。所以,"hello" 'world'"helloworld" 是等价的。这种特性可以用来减少需要的反斜杠数量,方便地在长行中拆分长字符串,甚至可以在字符串的某些部分添加注释,比如:

re.compile("[A-Za-z_]"       # letter or underscore
           "[A-Za-z0-9_]*"   # letter, digit or underscore
          )

需要注意的是,这个特性是在语法层面定义的,但在编译时实现。‘+’运算符必须在运行时用来连接字符串表达式。另外,字面量连接可以对每个部分使用不同的引号风格(甚至可以混合使用原始字符串和三重引号字符串)。

76

你可以通过给每个部分加上引号来拆分你的正则表达式模式。这样就不需要使用反斜杠了。

test = re.compile(
    ('(?P<full_path>.+):\d+:\s+warning:\s+Member'
     '\s+(?P<member_name>.+)\s+\((?P<member_type>%s)\) '
     'of (class|group|namespace)\s+(?P<class_name>.+)'
     '\s+is not documented'
    ) % (self.__MEMBER_TYPES),
    re.IGNORECASE)

你也可以使用原始字符串标志 'r',并且需要在每个部分前面加上这个标志。

查看文档:字符串字面量连接

撰写回答