在 Python 3 中使用正则表达式

如果您需要复习正则表达式的基本知识,请先查看我们的 交互式教程

Python 通过标准库 re 支持正则表达式,该库包含在每个 Python 安装包中。虽然此库并非完全兼容 PCRE,但它支持大多数常见的正则表达式用例。

请注意,此参考适用于 Python 3,如果您尚未更新,请参阅 Python 2 页面。

Python 原生字符串

在 Python 中编写正则表达式时,建议使用 原生字符串 而不是常规的 Python 字符串。原生字符串以特殊前缀 (r) 开头,并指示 Python 不要解释字符串中的反斜杠和特殊元字符,从而允许您将它们直接传递给正则表达式引擎。

这意味着像 "\n\w" 这样的模式不会被解释,并且可以写成 r"\n\w" 而不是像其他语言那样写成 "\\n\\w",这更容易阅读。

匹配字符串

re 包含许多顶级方法,要测试正则表达式是否匹配 Python 中的特定字符串,可以使用 re.search()。此方法如果模式不匹配则返回 None,否则返回一个包含有关在字符串的哪个部分找到匹配项的附加信息的 re.MatchObject

请注意,此方法在第一次匹配后停止,因此最适合于测试正则表达式而不是提取数据。

方法
matchObject = re.search(pattern, input_str, flags=0)
示例
import re # 让我们使用正则表达式来匹配一个日期字符串。忽略 # 输出,因为我们只是在测试正则表达式是否匹配。 regex = r"([a-zA-Z]+) (\d+)" if re.search(regex, "June 24"): # 确实,表达式 "([a-zA-Z]+) (\d+)" 匹配日期字符串      # 如果需要,我们可以使用 MatchObject 的 start() 和 end() 方法 # 来检索模式在输入字符串中的匹配位置,以及 # group() 方法获取所有匹配项和捕获组。 match = re.search(regex, "June 24")      # 这将打印 [0, 7),因为它匹配字符串的开头和结尾 # 字符串 print("Match at index %s, %s" % (match.start(), match.end()))      # 组包含匹配的值。特别是: # match.group(0) 始终返回完全匹配的字符串 # match.group(1)、match.group(2)、... 将按顺序返回捕获 # 组从左到右在输入字符串中 # match.group() 等效于 match.group(0)      # 因此这将打印 "June 24" print("Full match: %s" % (match.group(0))) # 因此这将打印 "June" print("Month: %s" % (match.group(1))) # 因此这将打印 "24" print("Day: %s" % (match.group(2))) else: # 如果 re.search() 不匹配,则返回 None print("The regex pattern does not match. :(")

捕获组

与上面的 re.search() 方法不同,我们可以使用 re.findall() 对整个输入字符串执行全局搜索。如果模式中存在捕获组,则它将返回所有捕获数据的列表,否则,它将只返回匹配项本身的列表,或者如果未找到任何匹配项则返回空列表。

如果您需要每个匹配项的其他上下文,可以使用 re.finditer(),它返回一个 re.MatchObjects 的迭代器以进行遍历。这两种方法都采用相同的参数。

方法
matchList = re.findall(pattern, input_str, flags=0)
matchList = re.finditer(pattern, input_str, flags=0)
示例
import re # 让我们使用正则表达式来匹配一些日期字符串。 regex = r"[a-zA-Z]+ \d+" matches = re.findall(regex, "June 24, August 9, Dec 12") for match in matches: # 这将打印: # June 24 # August 9 # Dec 12 print("Full match: %s" % (match)) # 要捕获每个日期的特定月份,我们可以使用以下模式 regex = r"([a-zA-Z]+) \d+" matches = re.findall(regex, "June 24, August 9, Dec 12") for match in matches: # 这现在将打印: # June # August # Dec print("Match month: %s" % (match)) # 如果我们需要每个匹配项的确切位置 regex = r"([a-zA-Z]+) \d+" matches = re.finditer(regex, "June 24, August 9, Dec 12") for match in matches: # 这现在将打印: # 0 7 # 9 17 # 19 25 # 这对应于输入字符串中每个匹配项的开始和结束位置 print("Match at index: %s, %s" % (match.start(), match.end()))

查找和替换字符串

另一个常见任务是使用正则表达式查找和替换字符串的一部分,例如,替换旧电子邮件域的所有实例,或交换某些文本的顺序。您可以在 Python 中使用 re.sub() 方法执行此操作。

可选的 count 参数是要在输入字符串中执行的替换的确切次数,如果此值为零或小于零,则替换字符串中的每个匹配项。

方法
replacedString = re.sub(pattern, replacement_pattern, input_str, count, flags=0)
示例
import re # 让我们尝试反转日期字符串中日期和月份的顺序 # 字符串。请注意,替换字符串也包含元字符 # (对捕获组的反向引用),因此我们也为其使用原生 # 字符串。 regex = r"([a-zA-Z]+) (\d+)" # 这将重新排序字符串并打印: # 24 of June, 9 of August, 12 of Dec print(re.sub(regex, r"\2 of \1", "June 24, August 9, Dec 12"))

re 标志

在上面 Python 正则表达式方法中,您会注意到它们都带有一个可选的 flags 参数。大多数可用标志都是为了方便起见,可以直接写入正则表达式本身,但在某些情况下,一些标志可能很有用。

  • re.IGNORECASE 使模式不区分大小写,以便它匹配不同大小写形式的字符串
  • re.MULTILINE 如果您的输入字符串包含换行符 (\n),则需要此标志,此标志允许开始和结束元字符 (分别为^$) 匹配每一行的开头和结尾,而不是整个输入字符串的开头和结尾
  • re.DOTALL 允许点 (.) 元字符匹配所有字符,包括换行符 (\n)

编译模式以提高性能

在 Python 中,创建一个新的正则表达式模式来匹配许多字符串可能很慢,因此,如果您需要使用相同的表达式测试或从许多输入字符串中提取信息,建议您编译它们。此方法返回一个 re.RegexObject

regexObject = re.compile(pattern, flags=0)

返回的对象具有与上面完全相同的方法,只是它们接受输入字符串,并且每次调用不再需要模式或标志。

import re # 让我们创建一个模式并使用它提取一些信息

链接

有关在 Python 中使用正则表达式的更多信息,请访问以下链接