Python进阶编程:编写更高效、优雅的Python代码
上QQ阅读APP看书,第一时间看更新

2.3.5 多行匹配

在实际应用中,我们有时需要跨越多行匹配一大块文本。

这个问题常出现在用点(.)字符去匹配任意字符的时候,但事实是点(.)字符不能匹配换行符,示例如下:


import re

anno_pat = re.compile(r'/\*(.*?)\*/')
text_1 = '/* this is one line annotation */'
text_2 = """/* this is
multi line annotation */
"""

print(anno_pat.findall(text_1))
print(anno_pat.findall(text_2))

对于以上问题,我们可以通过修改模式字符串,增加对换行的支持进行解决,示例如下:


anno_pat = re.compile(r'/\*((?:.|\n)*?)\*/')
print(anno_pat.findall(text_2))

在示例中,(?:.|\n)指定了一个非捕获组。也就是说,它定义了一个仅仅用来做匹配,而不能通过单独捕获或者编号的组。

re.compile()函数接收的一个标志参数叫re.DOTALL,该参数可以让正则表达式中的点(.)字符匹配包括换行符在内的任意字符,示例如下:


anno_pat = re.compile(r'/\*(.*?)\*/', re.DOTALL)
print(anno_pat.findall(text_2))

对于简单的情况,re.DOTALL标志参数可以工作得很好。但若模式非常复杂或者是为了构造字符串令牌而将多个模式合并起来,这时使用这个标志参数就可能出现一些问题。

如果可以选择,最好自定义正则表达式模式,这样不需要额外的标志参数程序也能工作得很好。