### 导航
- [索引](../genindex.xhtml "总目录")
- [模块](../py-modindex.xhtml "Python 模块索引") |
- [下一页](sockets.xhtml "套接字编程指南") |
- [上一页](logging-cookbook.xhtml "日志操作手册") |
- 
- [Python](https://www.python.org/) »
- zh\_CN 3.7.3 [文档](../index.xhtml) »
- [Python 常用指引](index.xhtml) »
- $('.inline-search').show(0); |
# 正则表达式HOWTO
作者A.M. Kuchling <[amk@amk.ca](mailto:amk%40amk.ca)>
摘要
本文档是在Python中使用 [`re`](../library/re.xhtml#module-re "re: Regular expression operations.") 模块使用正则表达式的入门教程。 它提供了比“标准库参考”中相应部分更平和的介绍。
## 概述
正则表达式(称为RE,或正则,或正则表达式模式)本质上是嵌入在Python中的一种微小的、高度专业化的编程语言,可通过 [`re`](../library/re.xhtml#module-re "re: Regular expression operations.") 模块获得。 使用这种小语言,你可以为要匹配的可能字符串集指定规则;此集可能包含英语句子,电子邮件地址,TeX命令或你喜欢的任何内容。 然后,您可以询问诸如“此字符串是否与模式匹配?”或“此字符串中的模式是否匹配?”等问题。 你还可以使用正则修改字符串或以各种方式将其拆分。
正则表达式模式被编译成一系列字节码,然后由用 C 编写的匹配引擎执行。对于高级用途,可能需要特别注意引擎如何执行给定的正则,并将正则写入以某种方式生成运行速度更快的字节码。 本文档未涉及优化,因为它要求你充分了解匹配引擎的内部结构。
正则表达式语言相对较小且受限制,因此并非所有可能的字符串处理任务都可以使用正则表达式完成。 还有一些任务 *可以* 用正则表达式完成,但表达式变得非常复杂。 在这些情况下,你最好编写 Python 代码来进行处理;虽然 Python 代码比精心设计的正则表达式慢,但它也可能更容易理解。
## 简单模式
我们首先要了解最简单的正则表达式。 由于正则表达式用于对字符串进行操作,因此我们将从最常见的任务开始:匹配字符。
有关正则表达式(确定性和非确定性有限自动机)的计算机科学的详细解释,你可以参考几乎所有有关编写编译器的教科书。
### 匹配字符
大多数字母和字符只会匹配自己。 例如,正则表达式 `test` 将完全匹配字符串 `test` 。 (你可以启用一个不区分大小写的模式,让这个正则匹配 `Test` 或 `TEST`,稍后会详细介绍。)
这条规则有例外;一些字符是特殊的 *metacharacters* ,并且不匹配自己。 相反,它们表示应该匹配一些与众不同的东西,或者通过重复它们或改变它们的含义来影响正则的其他部分。 本文档的大部分内容都致力于讨论各种元字符及其功能。
这是元字符的完整列表;它们的意思将在本HOWTO的其余部分讨论。
```
. ^ $ * + ? { } [ ] \ | ( )
```
我们将看到的第一个元字符是 `[``和`\]``。 它们用于指定字符类,它是你希望匹配的一组字符。 可以单独列出字符,也可以通过给出两个字符并用 `'-'` 标记将它们分开来表示一系列字符。 例如,`[abc]` 将匹配任何字符 `a`、`b` 或 `c`; 这与 `[a-c]` 相同,它使用一个范围来表示同一组字符。 如果你只想匹配小写字母,你的正则是 `[a-z]`。
字符类中的元字符不生效。 例如,`[akm$]` 将匹配``'a'`,`'k'`、`'m'`或`'$'`` 中的任意字符;`'$'` 通常是一个元字符,但在一个字符类中它被剥夺了特殊性。
你可以通过以下方式匹配 *complementing* 设置的字符类中未列出的字符。这通过包含一个 `'^'` 作为该类的第一个字符来表示。 例如,`[^5]` 将匹配除 `'5'` 之外的任何字符。 如果插入符出现在字符类的其他位置,则它没有特殊含义。 例如:`[5^]` 将匹配 `'5'` 或 `'^'`。
也许最重要的元字符是反斜杠,`\`。 与 Python 字符串文字一样,反斜杠后面可以跟各种字符,以指示各种特殊序列。它也用于转义所有元字符,因此您仍然可以在模式中匹配它们;例如,如果你需要匹配 `[` 或 `\`,你可以在它们前面加一个反斜杠来移除它们的特殊含义:`\[` 或 `\\`。
一些以 `'\'` 开头的特殊序列表示通常有用的预定义字符集,例如数字集、字母集或任何非空格的集合。
让我们举一个例子:`\w` 匹配任何字母数字字符。 如果正则表达式模式以字节类表示,这相当于类 `[a-zA-Z0-9_]`。如果正则表达式是一个字符串,`\w` 将匹配由 [`unicodedata`](../library/unicodedata.xhtml#module-unicodedata "unicodedata: Access the Unicode Database.") 模块提供的 Unicode 数据库中标记为字母的所有字符。 通过在编译正则表达式时提供 [`re.ASCII`](../library/re.xhtml#re.ASCII "re.ASCII") 标志,可以在字符串模式中使用更为受限制的 `\w` 定义。
以下特殊序列列表不完整。 有关 Unicode 字符串模式的序列和扩展类定义的完整列表,请参阅标准库参考中的最后一部分 [正则表达式语法](../library/re.xhtml#re-syntax) 。通常,Unicode 版本匹配 Unicode 数据库中相应类别中的任何字符。
`\d`匹配任何十进制数字;这等价于类 `[0-9]`。
`\D`匹配任何非数字字符;这等价于类 `[^0-9]`。
`\s`匹配任何空白字符;这等价于类 `[ \t\n\r\f\v]`。
`\S`匹配任何非空白字符;这相当于类 `[^ \t\n\r\f\v]`。
`\w`匹配任何字母与数字字符;这相当于类 `[a-zA-Z0-9_]`。
`\W`匹配任何非字母与数字字符;这相当于类 `[^a-zA-Z0-9_]`。
这些序列可以包含在字符类中。 例如,`[\s,.]` 是一个匹配任何空格字符的字符类或者 `','` ,或 `'.'`。
本节的最后一个元字符是 `.` 。 它匹配除换行符之外的任何内容,并且有一个可选模式( [`re.DOTALL`](../library/re.xhtml#re.DOTALL "re.DOTALL") )甚至可以匹配换行符。 `.` 常用于你想匹配“任何字符”的地方。
### 重复
能够匹配不同的字符集合是正则表达式可以做的第一件事,这对于字符串可用方法来说是不可能的。 但是,如果这是正则表达式的唯一额外功能,那么它们就不会有太大的优势。 另一个功能是你可以指定正则的某些部分必须重复一定次数。
重复中我们要了解的第一个元字符是 `*`。 `*` 与字面字符 `'*'` 不匹配;相反,它指定前一个字符可以匹配零次或多次,而不是恰好一次。
例如,`ca*t` 将匹配 `'ct'` (0个 `'a'` 字符),`'cat'` (1个``'a'`),` `'caaat'` (3个 `'a'` 字符),等等。
类似 `*` 这样的重复是 *贪婪的*;当重复正则时,匹配引擎将尝试尽可能多地重复它。 如果模式的后续部分不匹配,则匹配引擎将回退并以较少的重复次数再次尝试。
一个逐步的例子将使这更加明显。 让我们考虑表达式 `a[bcd]*b`。 这个正则匹配字母 `'a'`,类 `[bcd]` 中的零或多个字母,最后以 `'b'` 结尾。 现在想象一下这个正则与字符串 `'abcbd'` 匹配。
步骤
匹配
解释
1
`a`
正则中的 `a` 匹配。
2
`abcbd`
引擎尽可能多地匹配 `[bcd]*` ,直到字符串结束。
3
*失败*
引擎尝试匹配 `b` ,但是当前位置位于字符串结束,所以匹配失败。
4
`abcb`
回退一次,`[bcd]*` 少匹配一个字符。
5
*失败*
再次尝试匹配 `b` , 但是当前位置是最后一个字符 `'d'` 。
6
`abc`
再次回退,所以 `[bcd]*` 只匹配 `bc` 。
6
`abcb`
再试一次 `b` 。 这次当前位置的字符是 `'b'` ,所以它成功了。
正则现在已经结束了,它已经匹配了 `'abcb'`。 这演示了匹配引擎最初如何进行,如果没有找到匹配,它将逐步回退并一次又一次地重试正则的其余部分。 它将回退,直到它为 `[bcd]*` 尝试零匹配,如果随后失败,引擎将断定该字符串与正则完全不匹配。
另一个重复的元字符是 `+`,它匹配一次或多次。 要特别注意 `*` 和 `+` 之间的区别;`*` 匹配 *零次* 或更多次,因此重复的任何东西都可能根本不存在,而 `+` 至少需要 *一次*。 使用类似的例子,`ca+t` 将匹配 `'cat'` (1 个 `'a'`),`'caaat'` (3 个 `'a'`),但不会匹配 `'ct'`。
还有两个重复限定符。 问号字符 `?` 匹配一次或零次;你可以把它想象成是可选的。 例如,`home-?brew` 匹配 `'homebrew'` 或 `'home-brew'`。
最复杂的重复限定符是 `{m,n}`,其中 *m* 和 *n* 是十进制整数。 这个限定符意味着必须至少重复 *m* 次,最多重复 *n* 次。 例如,`a/{1,3}b` 将匹配 `'a/b'` ,`'a//b'` 和 `'a///b'` 。 它不匹配没有斜线的 `'ab'`,或者有四个的 `'a////b'`。
你可以省略 *m* 或 *n*; 在这种情况下,将假定缺失值的合理值。 省略 *m* 被解释为 0 下限,而省略 *n* 则为无穷大的上限。
还原论者的读者可能会注意到其他三个限定符都可以用这种表示法表达。 `{0,}``与``*``相同,``{1,}``相当于``+`,`{0,1}``和`?``相同。 最好使用``\*``,`+``或`?``,只要因为它们更短更容易阅读。
## 使用正则表达式
现在我们已经看了一些简单的正则表达式,我们如何在 Python 中实际使用它们? [`re`](../library/re.xhtml#module-re "re: Regular expression operations.") 模块提供了正则表达式引擎的接口,允许你将正则编译为对象,然后用它们进行匹配。
### 编译正则表达式
正则表达式被编译成模式对象,模式对象具有各种操作的方法,例如搜索模式匹配或执行字符串替换。:
```
>>> import re
>>> p = re.compile('ab*')
>>> p
re.compile('ab*')
```
[`re.compile()`](../library/re.xhtml#re.compile "re.compile") 也接受一个可选的 *flags* 参数,用于启用各种特殊功能和语法变体。 我们稍后将介绍可用的设置,但现在只需一个例子
```
>>> p = re.compile('ab*', re.IGNORECASE)
```
正则作为字符串传递给 [`re.compile()`](../library/re.xhtml#re.compile "re.compile") 。 正则被处理为字符串,因为正则表达式不是核心Python语言的一部分,并且没有创建用于表达它们的特殊语法。 (有些应用程序根本不需要正则,因此不需要通过包含它们来扩展语言规范。)相反,[`re`](../library/re.xhtml#module-re "re: Regular expression operations.") 模块只是Python附带的C扩展模块,就类似于 [`socket`](../library/socket.xhtml#module-socket "socket: Low-level networking interface.") 或 [`zlib`](../library/zlib.xhtml#module-zlib "zlib: Low-level interface to compression and decompression routines compatible with gzip.") 模块。
将正则放在字符串中可以使 Python 语言更简单,但有一个缺点是下一节的主题。
### 反斜杠灾难
如前所述,正则表达式使用反斜杠字符 (`'\'`) 来表示特殊形式或允许使用特殊字符而不调用它们的特殊含义。 这与 Python 在字符串文字中用于相同目的的相同字符的使用相冲突。
假设你想要编写一个与字符串 `\section` 相匹配的正则,它可以在 LaTeX 文件中找到。 要找出在程序代码中写入的内容,请从要匹配的字符串开始。 接下来,您必须通过在反斜杠前面添加反斜杠和其他元字符,从而产生字符串 `\\section`。 必须传递给 [`re.compile()`](../library/re.xhtml#re.compile "re.compile") 的结果字符串必须是 `\\section`。 但是,要将其表示为 Python 字符串文字,必须 *再次* 转义两个反斜杠。
字符
阶段
`\section`
被匹配的字符串
`\\section`
为 [`re.compile()`](../library/re.xhtml#re.compile "re.compile") 转义的反斜杠
`"\\\\section"`
为字符串字面转义的反斜杠
简而言之,要匹配文字反斜杠,必须将 `'\\\\'` 写为正则字符串,因为正则表达式必须是 `\\`,并且每个反斜杠必须表示为 `\\` 在常规Python字符串字面中。 在反复使用反斜杠的正则中,这会导致大量重复的反斜杠,并使得生成的字符串难以理解。
解决方案是使用 Python 的原始字符串表示法来表示正则表达式;反斜杠不以任何特殊的方式处理前缀为 `'r'` 的字符串字面,因此 `r"\n"` 是一个包含 `'\'` 和 `'n'` 的双字符字符串,而 `"\n"` 是一个包含换行符的单字符字符串。 正则表达式通常使用这种原始字符串表示法用 Python 代码编写。
此外,在正则表达式中有效但在 Python 字符串文字中无效的特殊转义序列现在导致 [`DeprecationWarning`](../library/exceptions.xhtml#DeprecationWarning "DeprecationWarning") 并最终变为 [`SyntaxError`](../library/exceptions.xhtml#SyntaxError "SyntaxError")。 这意味着如果未使用原始字符串表示法或转义反斜杠,序列将无效。
常规字符串
原始字符串
`"ab*"`
`r"ab*"`
`"\\\\section"`
`r"\\section"`
`"\\w+\\s+\\1"`
`r"\w+\s+\1"`
### 应用匹配
一旦你有一个表示编译正则表达式的对象,你用它做什么? 模式对象有几种方法和属性。 这里只介绍最重要的内容;请参阅 [`re`](../library/re.xhtml#module-re "re: Regular expression operations.") 文档获取完整列表。
方法 / 属性
目的
`match()`
确定正则是否从字符串的开头匹配。
`search()`
扫描字符串,查找此正则匹配的任何位置。
`findall()`
找到正则匹配的所有子字符串,并将它们作为列表返回。
`finditer()`
找到正则匹配的所有子字符串,并将它们返回为一个 [iterator](../glossary.xhtml#term-iterator)。
如果没有找到匹配, [`match()`](../library/re.xhtml#re.Pattern.match "re.Pattern.match") 和 [`search()`](../library/re.xhtml#re.Pattern.search "re.Pattern.search") 返回 `None` 。如果它们成功, 一个 [匹配对象](../library/re.xhtml#match-objects) 实例将被返回,包含匹配相关的信息:起始和终结位置、匹配的子串以及其它。
你可以通过交互式实验 [`re`](../library/re.xhtml#module-re "re: Regular expression operations.") 模块来了解这一点。 如果你有 [`tkinter`](../library/tkinter.xhtml#module-tkinter "tkinter: Interface to Tcl/Tk for graphical user interfaces"),你可能还想查看 [Tools/demo/redemo.py](https://github.com/python/cpython/tree/3.7/Tools/demo/redemo.py) \[https://github.com/python/cpython/tree/3.7/Tools/demo/redemo.py\],这是 Python 发行附带的演示程序。 它允许你输入正则和字符串,并显示RE是匹配还是失败。 `redemo.py` 在尝试调试复杂的正则时非常有用。
本 HOWTO 使用标准 Python 解释器作为示例。 首先,运行 Python 解释器,导入 [`re`](../library/re.xhtml#module-re "re: Regular expression operations.") 模块,然后编译一个正则
```
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
re.compile('[a-z]+')
```
现在,你可以尝试匹配正则 `[a-z]+` 的各种字符串。 空字符串根本不匹配,因为 `+` 表示“一次或多次重复”。 [`match()`](../library/re.xhtml#re.Pattern.match "re.Pattern.match") 在这种情况下应返回 `None`,这将导致解释器不打印输出。 你可以显式打印 `match()` 的结果,使其清晰。:
```
>>> p.match("")
>>> print(p.match(""))
None
```
现在,让我们尝试一下它应该匹配的字符串,例如 `tempo`。在这个例子中 [`match()`](../library/re.xhtml#re.Pattern.match "re.Pattern.match") 将返回一个 [匹配对象](../library/re.xhtml#match-objects),因此你应该将结果储存到一个变量中以供稍后使用。
```
>>> m = p.match('tempo')
>>> m
<re.Match object; span=(0, 5), match='tempo'>
```
现在你可以检查 [匹配对象](../library/re.xhtml#match-objects) 以获取有关匹配字符串的信息。 匹配对象实例也有几个方法和属性;最重要的是:
方法 / 属性
目的
`group()`
返回正则匹配的字符串
`start()`
返回匹配的开始位置
`end()`
返回匹配的结束位置
`span()`
返回包含匹配 (start, end) 位置的元组
尝试这些方法很快就会清楚它们的含义:
```
>>> m.group()
'tempo'
>>> m.start(), m.end()
(0, 5)
>>> m.span()
(0, 5)
```
[`group()`](../library/re.xhtml#re.Match.group "re.Match.group") 返回正则匹配的子字符串。 [`start()`](../library/re.xhtml#re.Match.start "re.Match.start") 和 [`end()`](../library/re.xhtml#re.Match.end "re.Match.end") 返回匹配的起始和结束索引。 [`span()`](../library/re.xhtml#re.Match.span "re.Match.span") 在单个元组中返回开始和结束索引。 由于 [`match()`](../library/re.xhtml#re.Pattern.match "re.Pattern.match") 方法只检查正则是否在字符串的开头匹配,所以 `start()` 将始终为零。 但是,模式的 [`search()`](../library/re.xhtml#re.Pattern.search "re.Pattern.search") 方法会扫描字符串,因此在这种情况下匹配可能不会从零开始。:
```
>>> print(p.match('::: message'))
None
>>> m = p.search('::: message'); print(m)
<re.Match object; span=(4, 11), match='message'>
>>> m.group()
'message'
>>> m.span()
(4, 11)
```
在实际程序中,最常见的样式是在变量中存储 [匹配对象](../library/re.xhtml#match-objects),然后检查它是否为 `None`。 这通常看起来像:
```
p = re.compile( ... )
m = p.match( 'string goes here' )
if m:
print('Match found: ', m.group())
else:
print('No match')
```
两种模式方法返回模式的所有匹配项。 [`findall()`](../library/re.xhtml#re.Pattern.findall "re.Pattern.findall") 返回匹配字符串的列表:
```
>>> p = re.compile(r'\d+')
>>> p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping')
['12', '11', '10']
```
在这个例子中需要 `r` 前缀,使字面为原始字符串字面,因为普通的“加工”字符串字面中的转义序列不能被 Python 识别为正则表达式,导致 [`DeprecationWarning`](../library/exceptions.xhtml#DeprecationWarning "DeprecationWarning") 并最终产生 [`SyntaxError`](../library/exceptions.xhtml#SyntaxError "SyntaxError")。 请参阅 [反斜杠灾难](#the-backslash-plague)。
[`findall()`](../library/re.xhtml#re.Pattern.findall "re.Pattern.findall") 必须先创建整个列表才能返回结果。 [`finditer()`](../library/re.xhtml#re.Pattern.finditer "re.Pattern.finditer") 方法将一个 [匹配对象](../library/re.xhtml#match-objects) 的序列返回为一个 [iterator](../glossary.xhtml#term-iterator)
```
>>> iterator = p.finditer('12 drummers drumming, 11 ... 10 ...')
>>> iterator
<callable_iterator object at 0x...>
>>> for match in iterator:
... print(match.span())
...
(0, 2)
(22, 24)
(29, 31)
```
### 模块级别函数
你不必创建模式对象并调用其方法;[`re`](../library/re.xhtml#module-re "re: Regular expression operations.") 模块还提供了顶级函数 [`match()`](../library/re.xhtml#re.match "re.match"),[`search()`](../library/re.xhtml#re.search "re.search"),[`findall()`](../library/re.xhtml#re.findall "re.findall"),[`sub()`](../library/re.xhtml#re.sub "re.sub") 等等。 这些函数采用与相应模式方法相同的参数,并将正则字符串作为第一个参数添加,并仍然返回 `None` 或 [匹配对象](../library/re.xhtml#match-objects) 实例。:
```
>>> print(re.match(r'From\s+', 'Fromage amk'))
None
>>> re.match(r'From\s+', 'From amk Thu May 14 19:12:10 1998')
<re.Match object; span=(0, 5), match='From '>
```
本质上,这些函数只是为你创建一个模式对象,并在其上调用适当的方法。 它们还将编译对象存储在缓存中,因此使用相同的未来调用将不需要一次又一次地解析该模式。
你是否应该使用这些模块级函数,还是应该自己获取模式并调用其方法? 如果你正在循环中访问正则表达式,预编译它将节省一些函数调用。 在循环之外,由于有内部缓存,没有太大区别。
### 编译标志
编译标志允许你修改正则表达式的工作方式。 标志在 [`re`](../library/re.xhtml#module-re "re: Regular expression operations.") 模块中有两个名称,长名称如 `IGNORECASE` 和一个简短的单字母形式,例如 `I`。 (如果你熟悉 Perl 的模式修饰符,则单字母形式使用和其相同的字母;例如, [`re.VERBOSE`](../library/re.xhtml#re.VERBOSE "re.VERBOSE") 的缩写形式为 [`re.X`](../library/re.xhtml#re.X "re.X")。)多个标志可以 通过按位或运算来指定它们;例如,`re.I | re.M` 设置 `I` 和 `M` 标志。
这是一个可用标志表,以及每个标志的更详细说明。
标志
意义
`ASCII`, `A`
使几个转义如 `\w`、`\b`、`\s` 和 `\d` 匹配仅与具有相应特征属性的 ASCII 字符匹配。
`DOTALL`, `S`
使 `.` 匹配任何字符,包括换行符。
`IGNORECASE`, `I`
进行大小写不敏感匹配。
`LOCALE`, `L`
进行区域设置感知匹配。
`MULTILINE`, `M`
多行匹配,影响 `^` 和 `$`。
`VERBOSE`, `X` (为 '扩展')
启用详细的正则,可以更清晰,更容易理解。
`I``IGNORECASE`执行不区分大小写的匹配;字符类和字面字符串将通过忽略大小写来匹配字母。 例如,`[A-Z]` 也匹配小写字母。 除非使用 `ASCII` 标志来禁用非ASCII匹配,否则完全 Unicode 匹配也有效。 当 Unicode 模式 `[a-z]` 或 `[A-Z]` 与 `IGNORECASE` 标志结合使用时,它们将匹配 52 个 ASCII 字母和 4 个额外的非 ASCII 字母:'İ' (U+0130,拉丁大写字母 I,带上面的点),'ı' (U+0131,拉丁文小写字母无点 i),'s' (U+017F,拉丁文小写字母长 s) 和'K' (U+212A,开尔文符号)。 `Spam` 将匹配 `'Spam'`,`'spam'`,`'spAM'` 或 `'ſpam'` (后者仅在 Unicode 模式下匹配)。 此小写不考虑当前区域设置;如果你还设置了 `LOCALE` 标志,则将考虑。
`L``LOCALE`使 `\w`、`\W`、`\b`、`\B` 和大小写敏感匹配依赖于当前区域而不是 Unicode 数据库。
区域设置是 C 库的一个功能,旨在帮助编写考虑到语言差异的程序。例如,如果你正在处理编码的法语文本,那么你希望能够编写 `\w+` 来匹配单词,但 `\w` 只匹配字符类 `[A-Za-z]` 字节模式;它不会匹配对应于 `é` 或 `ç` 的字节。如果你的系统配置正确并且选择了法语区域设置,某些C函数将告诉程序对应于 `é` 的字节也应该被视为字母。在编译正则表达式时设置 `LOCALE` 标志将导致生成的编译对象将这些C函数用于 `\w`;这比较慢,但也可以使 `\w+` 匹配你所期望的法语单词。在 Python 3 中不鼓励使用此标志,因为语言环境机制非常不可靠,它一次只处理一个“文化”,它只适用于 8 位语言环境。默认情况下,Python 3 中已经为 Unicode(str)模式启用了 Unicode 匹配,并且它能够处理不同的区域/语言。
`M``MULTILINE`(`^` 和 `$` 还没有解释;它们将在以下部分介绍 [更多元字符](#more-metacharacters)。)
通常 `^` 只匹配字符串的开头,而 `$` 只匹配字符串的结尾,紧接在字符串末尾的换行符(如果有的话)之前。 当指定了这个标志时,`^` 匹配字符串的开头和字符串中每一行的开头,紧跟在每个换行符之后。 类似地,`$` 元字符匹配字符串的结尾和每行的结尾(紧接在每个换行符之前)。
`S``DOTALL`使 `'.'` 特殊字符匹配任何字符,包括换行符;没有这个标志,`'.'` 将匹配任何字符 *除了* 换行符。
`A``ASCII`使 `\w`、`\W`、`\b`、`\B`、`\s` 和 `\S` 执行仅 ASCII 匹配而不是完整匹配 Unicode 匹配。 这仅对 Unicode 模式有意义,并且对于字节模式将被忽略。
`X``VERBOSE`此标志允许你编写更易读的正则表达式,方法是为您提供更灵活的格式化方式。 指定此标志后,将忽略正则字符串中的空格,除非空格位于字符类中或前面带有未转义的反斜杠;这使你可以更清楚地组织和缩进正则。 此标志还允许你将注释放在正则中,引擎将忽略该注释;注释标记为 `'#'` 既不是在字符类中,也不是在未转义的反斜杠之前。
例如,这里的正则使用 [`re.VERBOSE`](../library/re.xhtml#re.VERBOSE "re.VERBOSE");看看阅读有多容易?:
```
charref = re.compile(r"""
&[#] # Start of a numeric entity reference
(
0[0-7]+ # Octal form
| [0-9]+ # Decimal form
| x[0-9a-fA-F]+ # Hexadecimal form
)
; # Trailing semicolon
""", re.VERBOSE)
```
如果没有详细设置,正则将如下所示:
```
charref = re.compile("&#(0[0-7]+"
"|[0-9]+"
"|x[0-9a-fA-F]+);")
```
在上面的例子中,Python的字符串文字的自动连接已被用于将正则分解为更小的部分,但它仍然比以下使用 [`re.VERBOSE`](../library/re.xhtml#re.VERBOSE "re.VERBOSE") 版本更难理解。
## 更多模式能力
到目前为止,我们只介绍了正则表达式的一部分功能。 在本节中,我们将介绍一些新的元字符,以及如何使用组来检索匹配的文本部分。
### 更多元字符
我们还没有涉及到一些元字符。 其中大部分内容将在本节中介绍。
要讨论的其余一些元字符是 *零宽度断言* 。 它们不会使解析引擎在字符串中前进一个字符;相反,它们根本不占用任何字符,只是成功或失败。例如,`\b` 是一个断言,指明当前位置位于字边界;这个位置根本不会被 `\b` 改变。这意味着永远不应重复零宽度断言,因为如果它们在给定位置匹配一次,它们显然可以无限次匹配。
`|`或者“or”运算符。 如果 *A* 和 *B* 是正则表达式,`A|B` 将匹配任何与 *A* 或 *B* 匹配的字符串。 `|` 具有非常低的优先级,以便在交替使用多字符字符串时使其合理地工作。 `Crow|Servo` 将匹配 `'Crow'` 或 `'Servo'`,而不是 `'Cro'`、`'w'` 或 `'S'` 和 `'ervo'`。
要匹配字面 `'|'`,请使用 `\|`,或将其括在字符类中,如 `[|]`。
`^`在行的开头匹配。 除非设置了 `MULTILINE` 标志,否则只会在字符串的开头匹配。 在 `MULTILINE` 模式下,这也在字符串中的每个换行符后立即匹配。
例如,如果你希望仅在行的开头匹配单词 `From`,则要使用的正则 `^From`。:
```
>>> print(re.search('^From', 'From Here to Eternity'))
<re.Match object; span=(0, 4), match='From'>
>>> print(re.search('^From', 'Reciting From Memory'))
None
```
要匹配字面 `'^'`,使用 `\^`。
`$`匹配行的末尾,定义为字符串的结尾,或者后跟换行符的任何位置。:
```
>>> print(re.search('}$', '{block}'))
<re.Match object; span=(6, 7), match='}'>
>>> print(re.search('}$', '{block} '))
None
>>> print(re.search('}$', '{block}\n'))
<re.Match object; span=(6, 7), match='}'>
```
以匹配字面 `'$'`,使用 `\$` 或者将其包裹在一个字符类中,例如 `[$]`。
`\A`仅匹配字符串的开头。 当不在 `MULTILINE` 模式时,`\A` 和 `^` 实际上是相同的。 在 `MULTILINE` 模式中,它们是不同的: `\A` 仍然只在字符串的开头匹配,但 `^` 可以匹配在换行符之后的字符串内的任何位置。
`\Z`只匹配字符串尾。
`\b`字边界。 这是一个零宽度断言,仅在单词的开头或结尾处匹配。 单词被定义为一个字母数字字符序列,因此单词的结尾由空格或非字母数字字符表示。
以下示例仅当它是一个完整的单词时匹配 `class`;当它包含在另一个单词中时将不会匹配。
```
>>> p = re.compile(r'\bclass\b')
>>> print(p.search('no class at all'))
<re.Match object; span=(3, 8), match='class'>
>>> print(p.search('the declassified algorithm'))
None
>>> print(p.search('one subclass is'))
None
```
使用这个特殊序列时,你应该记住两个细微之处。 首先,这是 Python 的字符串文字和正则表达式序列之间最严重的冲突。 在 Python 的字符串文字中,`\b` 是退格字符,ASCII 值为8。 如果你没有使用原始字符串,那么 Python 会将 `\b` 转换为退格,你的正则不会按照你的预期匹配。 以下示例与我们之前的正则看起来相同,但省略了正则字符串前面的 `'r'`。:
```
>>> p = re.compile('\bclass\b')
>>> print(p.search('no class at all'))
None
>>> print(p.search('\b' + 'class' + '\b'))
<re.Match object; span=(0, 7), match='\x08class\x08'>
```
其次,在一个字符类中,这个断言没有用处,`\b` 表示退格字符,以便与 Python 的字符串文字兼容。
`\B`另一个零宽度断言,这与 `\b` 相反,仅在当前位置不在字边界时才匹配。
### 分组
通常,你需要获取更多信息,而不仅仅是正则是否匹配。 正则表达式通常用于通过将正则分成几个子组来解析字符串,这些子组匹配不同的感兴趣组件。 例如,RFC-822 标题行分为标题名称和值,用 `':'` 分隔,如下所示:
```
From: author@example.com
User-Agent: Thunderbird 1.5.0.9 (X11/20061227)
MIME-Version: 1.0
To: editor@example.com
```
这可以通过编写与整个标题行匹配的正则表达式来处理,并且具有与标题名称匹配的一个组,以及与标题的值匹配的另一个组。
组由 `'('`,`')'`` 元字符标记。 `'('` 和 `')'` 与数学表达式的含义大致相同;它们将包含在其中的表达式组合在一起,你可以使用重复限定符重复组的内容,例如 `*`,`+`,`?` 或 `{m,n}`。 例如,`(ab)*` 将匹配 `ab` 的零次或多次重复。:
```
>>> p = re.compile('(ab)*')
>>> print(p.match('ababababab').span())
(0, 10)
```
用 `'('`,`')'` 表示的组也捕获它们匹配的文本的起始和结束索引;这可以通过将参数传递给 [`group()`](../library/re.xhtml#re.Match.group "re.Match.group")、[`start()`](../library/re.xhtml#re.Match.start "re.Match.start")、[`end()`](../library/re.xhtml#re.Match.end "re.Match.end") 以及 [`span()`](../library/re.xhtml#re.Match.span "re.Match.span")。 组从 0 开始编号。组 0 始终存在;它表示整个正则,所以 [匹配对象](../library/re.xhtml#match-objects) 方法都将组 0 作为默认参数。 稍后我们将看到如何表达不捕获它们匹配的文本范围的组。:
```
>>> p = re.compile('(a)b')
>>> m = p.match('ab')
>>> m.group()
'ab'
>>> m.group(0)
'ab'
```
子组从左到右编号,从 1 向上编号。 组可以嵌套;要确定编号,只需计算从左到右的左括号字符。:
```
>>> p = re.compile('(a(b)c)d')
>>> m = p.match('abcd')
>>> m.group(0)
'abcd'
>>> m.group(1)
'abc'
>>> m.group(2)
'b'
```
[`group()`](../library/re.xhtml#re.Match.group "re.Match.group") 可以一次传递多个组号,在这种情况下,它将返回一个包含这些组的相应值的元组。:
```
>>> m.group(2,1,2)
('b', 'abc', 'b')
```
[`groups()`](../library/re.xhtml#re.Match.groups "re.Match.groups") 方法返回一个元组,其中包含所有子组的字符串,从1到最后一个子组。:
```
>>> m.groups()
('abc', 'b')
```
模式中的后向引用允许你指定还必须在字符串中的当前位置找到先前捕获组的内容。 例如,如果可以在当前位置找到组 1 的确切内容,则 `\1` 将成功,否则将失败。 请记住,Python 的字符串文字也使用反斜杠后跟数字以允许在字符串中包含任意字符,因此正则中引入反向引用时务必使用原始字符串。
例如,以下正则检测字符串中的双字。:
```
>>> p = re.compile(r'\b(\w+)\s+\1\b')
>>> p.search('Paris in the the spring').group()
'the the'
```
像这样的后向引用通常不仅仅用于搜索字符串 —— 很少有文本格式以这种方式重复数据 —— 但是你很快就会发现它们在执行字符串替换时 *非常* 有用。
### 非捕获和命名组
精心设计的正则可以使用许多组,既可以捕获感兴趣的子串,也可以对正则本身进行分组和构建。 在复杂的正则中,很难跟踪组号。 有两个功能可以帮助解决这个问题。 它们都使用常用语法进行正则表达式扩展,因此我们首先看一下。
Perl 5 以其对标准正则表达式的强大补充而闻名。 对于这些新功能,Perl 开发人员无法选择新的单键击元字符或以 `\` 开头的新特殊序列,否则 Perl 的正则表达式与标准正则容易混淆。 例如,如果他们选择 `&` 作为一个新的元字符,旧的表达式将假设 `&` 是一个普通字符,并且不会编写 `\&` 或 `[&]`。
Perl 开发人员选择的解决方案是使用 `(?...)` 作为扩展语法。 括号后面的 `?` 是一个语法错误,因为 `?` 没有什么可重复的,所以这并没有引入任何兼容性问题。 紧跟在 `?` 之后的字符表示正在使用什么扩展名,所以 `(?=foo)` 是一个东西(一个正向的先行断言)和 `(?:foo)` 是其它东西( 包含子表达式 `foo` 的非捕获组)。
Python 支持一些 Perl 的扩展,并增加了新的扩展语法用于 Perl 的扩展语法。 如果在问号之后的第一个字符为 `P`,即表明其为 Python 专属的扩展。
现在我们已经了解了一般的扩展语法,我们可以回到简化复杂正则中组处理的功能。
有时你会想要使用组来表示正则表达式的一部分,但是对检索组的内容不感兴趣。 你可以通过使用非捕获组来显式表达这个事实: `(?:...)`,你可以用任何其他正则表达式替换 `...`。:
```
>>> m = re.match("([abc])+", "abc")
>>> m.groups()
('c',)
>>> m = re.match("(?:[abc])+", "abc")
>>> m.groups()
()
```
除了你无法检索组匹配内容的事实外,非捕获组的行为与捕获组完全相同;你可以在里面放任何东西,用重复元字符重复它,比如 `*`,然后把它嵌入其他组(捕获或不捕获)。 `(?:...)` 在修改现有模式时特别有用,因为你可以添加新组而不更改所有其他组的编号方式。 值得一提的是,捕获和非捕获组之间的搜索没有性能差异;两种形式没有一种更快。
更重要的功能是命名组:不是通过数字引用它们,而是可以通过名称引用组。
命名组的语法是Python特定的扩展之一: `(?P<name>...)`。 *name* 显然是该组的名称。 命名组的行为与捕获组完全相同,并且还将名称与组关联。 处理捕获组的 [匹配对象](../library/re.xhtml#match-objects) 方法都接受按编号引用组的整数或包含所需组名的字符串。 命名组仍然是给定的数字,因此你可以通过两种方式检索有关组的信息:
```
>>> p = re.compile(r'(?P<word>\b\w+\b)')
>>> m = p.search( '(((( Lots of punctuation )))' )
>>> m.group('word')
'Lots'
>>> m.group(1)
'Lots'
```
命名组很有用,因为它们允许你使用容易记住的名称,而不必记住数字。 这是来自 [`imaplib`](../library/imaplib.xhtml#module-imaplib "imaplib: IMAP4 protocol client (requires sockets).") 模块的示例正则
```
InternalDate = re.compile(r'INTERNALDATE "'
r'(?P<day>[ 123][0-9])-(?P<mon>[A-Z][a-z][a-z])-'
r'(?P<year>[0-9][0-9][0-9][0-9])'
r' (?P<hour>[0-9][0-9]):(?P<min>[0-9][0-9]):(?P<sec>[0-9][0-9])'
r' (?P<zonen>[-+])(?P<zoneh>[0-9][0-9])(?P<zonem>[0-9][0-9])'
r'"')
```
检索 `m.group('zonem')` 显然要容易得多,而不必记住检索第 9 组。
表达式中的后向引用语法,例如 `(...)\1`,指的是组的编号。 当然有一种变体使用组名而不是数字。 这是另一个 Python 扩展: `(?P=name)` 表示在当前点再次匹配名为 *name* 的组的内容。 用于查找双字的正则表达式,`\b(\w+)\s+\1\b` 也可以写为 `\b(?P<word>\w+)\s+(?P=word)\b`:
```
>>> p = re.compile(r'\b(?P<word>\w+)\s+(?P=word)\b')
>>> p.search('Paris in the the spring').group()
'the the'
```
### 前向断言
另一个零宽度断言是前向断言。 前向断言以正面和负面形式提供,如下所示:
`(?=…)`正向前向断言。 如果包含的正则表达式,由 `...` 表示,在当前位置成功匹配,则成功,否则失败。 但是,一旦尝试了包含的表达式,匹配的引擎就不会前进;模式其余的部分会在在断言开始的地方尝试。
`(?!…)`负向前向断言。 这与积正向断言相反;如果包含的表达式在字符串中的当前位置 *不* 匹配,则成功。
更具体一些,让我们看看前向是有用的情况。 考虑一个简单的模式来匹配文件名并将其拆分为基本名称和扩展名,用 `.` 分隔。 例如,在 `news.rc` 中,`news` 是基本名称,`rc` 是文件名的扩展名。
与此匹配的模式非常简单:
`.*[.].*$`
请注意,`.` 需要特别处理,因为它是元字符,所以它在字符类中只能匹配特定字符。 还要注意尾随的 `$`;添加此项以确保扩展名中的所有其余字符串都必须包含在扩展名中。 这个正则表达式匹配 `foo.bar`、`autoexec.bat`、`sendmail.cf` 和 `printers.conf`。
现在,考虑使更复杂一点的问题;如果你想匹配扩展名不是 `bat` 的文件名怎么办? 一些错误的尝试:
`.*[.][^b].*$` 上面的第一次尝试试图通过要求扩展名的第一个字符不是 `b` 来排除 `bat`。 这是错误的,因为模式也与 `foo.bar` 不匹配。
`.*[.]([^b]..|.[^a].|..[^t])$`
当你尝试通过要求以下一种情况匹配来修补第一个解决方案时,表达式变得更加混乱:扩展的第一个字符不是 `b`。 第二个字符不 `a`;或者第三个字符不是 `t`。 这接受 `foo.bar` 并拒绝 `autoexec.bat`,但它需要三个字母的扩展名,并且不接受带有两个字母扩展名的文件名,例如 `sendmail.cf`。 为了解决这个问题,我们会再次使模式复杂化。
`.*[.]([^b].?.?|.[^a]?.?|..?[^t]?)$`
在第三次尝试中,第二个和第三个字母都是可选的,以便允许匹配的扩展名短于三个字符,例如 `sendmail.cf`。
模式现在变得非常复杂,这使得它难以阅读和理解。 更糟糕的是,如果问题发生变化并且你想要将 `bat` 和 `exe` 排除为扩展,那么该模式将变得更加复杂和混乱。
负面前向消除了所有这些困扰:
`.*[.](?!bat$)[^.]*$` 负向前向意味着:如果表达式 `bat` 此时不匹配,请尝试其余的模式;如果 `bat$` 匹配,整个模式将失败。 尾随的 `$` 是必需的,以确保允许像 `sample.batch` 这样的扩展只以 `bat` 开头的文件能通过。 `[^.]*` 确保当文件名中有多个点时,模式有效。
现在很容易排除另一个文件扩展名;只需在断言中添加它作为替代。 以下模块排除以 `bat` 或 `exe`:
`.*[.](?!bat$|exe$)[^.]*$`
## 修改字符串
到目前为止,我们只是针对静态字符串执行搜索。 正则表达式通常也用于以各种方式修改字符串,使用以下模式方法:
方法 / 属性
目的
`split()`
将字符串拆分为一个列表,在正则匹配的任何地方将其拆分
`sub()`
找到正则匹配的所有子字符串,并用不同的字符串替换它们
`subn()`
与 `sub()` 相同,但返回新字符串和替换次数
### 分割字符串
模式的 [`split()`](../library/re.xhtml#re.Pattern.split "re.Pattern.split") 方法在正则匹配的任何地方拆分字符串,返回一个片段列表。 它类似于 [`split()`](../library/stdtypes.xhtml#str.split "str.split") 字符串方法,但在分隔符的分隔符中提供了更多的通用性;字符串的 `split()` 仅支持按空格或固定字符串进行拆分。 正如你所期望的那样,还有一个模块级 [`re.split()`](../library/re.xhtml#re.split "re.split") 函数。
`.``split`(*string*\[, *maxsplit=0*\])通过正则表达式的匹配拆分 *字符串*。 如果在正则中使用捕获括号,则它们的内容也将作为结果列表的一部分返回。 如果 *maxsplit* 非零,则最多执行 *maxsplit* 次拆分。
你可以通过传递 *maxsplit* 的值来限制分割的数量。 当 *maxsplit* 非零时,将最多进行 *maxsplit* 次拆分,并且字符串的其余部分将作为列表的最后一个元素返回。 在以下示例中,分隔符是任何非字母数字字符序列。:
```
>>> p = re.compile(r'\W+')
>>> p.split('This is a test, short and sweet, of split().')
['This', 'is', 'a', 'test', 'short', 'and', 'sweet', 'of', 'split', '']
>>> p.split('This is a test, short and sweet, of split().', 3)
['This', 'is', 'a', 'test, short and sweet, of split().']
```
有时你不仅对分隔符之间的文本感兴趣,而且还需要知道分隔符是什么。 如果在正则中使用捕获括号,则它们的值也将作为列表的一部分返回。 比较以下调用:
```
>>> p = re.compile(r'\W+')
>>> p2 = re.compile(r'(\W+)')
>>> p.split('This... is a test.')
['This', 'is', 'a', 'test', '']
>>> p2.split('This... is a test.')
['This', '... ', 'is', ' ', 'a', ' ', 'test', '.', '']
```
模块级函数 [`re.split()`](../library/re.xhtml#re.split "re.split") 添加要正则作为第一个参数,但在其他方面是相同的。:
```
>>> re.split(r'[\W]+', 'Words, words, words.')
['Words', 'words', 'words', '']
>>> re.split(r'([\W]+)', 'Words, words, words.')
['Words', ', ', 'words', ', ', 'words', '.', '']
>>> re.split(r'[\W]+', 'Words, words, words.', 1)
['Words', 'words, words.']
```
### 搜索和替换
另一个常见任务是找到模式的所有匹配项,并用不同的字符串替换它们。 [`sub()`](../library/re.xhtml#re.Pattern.sub "re.Pattern.sub") 方法接受一个替换值,可以是字符串或函数,也可以是要处理的字符串。
`.``sub`(*replacement*, *string*\[, *count=0*\])返回通过替换 *replacement* 替换 *string* 中正则的最左边非重叠出现而获得的字符串。 如果未找到模式,则 *string* 将保持不变。
可选参数 *count* 是要替换的模式最大的出现次数;*count* 必须是非负整数。 默认值 0 表示替换所有。
这是一个使用 [`sub()`](../library/re.xhtml#re.Pattern.sub "re.Pattern.sub") 方法的简单示例。 它用 `colour` 这个词取代颜色名称:
```
>>> p = re.compile('(blue|white|red)')
>>> p.sub('colour', 'blue socks and red shoes')
'colour socks and colour shoes'
>>> p.sub('colour', 'blue socks and red shoes', count=1)
'colour socks and red shoes'
```
[`subn()`](../library/re.xhtml#re.Pattern.subn "re.Pattern.subn") 方法完成相同的工作,但返回一个包含新字符串值和已执行的替换次数的 2 元组:
```
>>> p = re.compile('(blue|white|red)')
>>> p.subn('colour', 'blue socks and red shoes')
('colour socks and colour shoes', 2)
>>> p.subn('colour', 'no colours at all')
('no colours at all', 0)
```
仅当空匹配与前一个空匹配不相邻时,才会替换空匹配。:
```
>>> p = re.compile('x*')
>>> p.sub('-', 'abxd')
'-a-b--d-'
```
如果 *replacement* 是一个字符串,则处理其中的任何反斜杠转义。 也就是说,`\n` 被转换为单个换行符,`\r` 被转换为回车符,依此类推。 诸如 `\&` 之类的未知转义是孤立的。 后向引用,例如 `\6`,被替换为正则中相应组匹配的子字符串。 这使你可以在生成的替换字符串中合并原始文本的部分内容。
这个例子匹配单词 `section` 后跟一个用 `{`,`}` 括起来的字符串,并将 `section` 改为 `subsection`
```
>>> p = re.compile('section{ ( [^}]* ) }', re.VERBOSE)
>>> p.sub(r'subsection{\1}','section{First} section{second}')
'subsection{First} subsection{second}'
```
还有一种语法用于引用由 `(?P<name>...)` 语法定义的命名组。 `\g<name>` 将使用名为 `name` 的组匹配的子字符串,`\g<number>` 使用相应的组号。 因此 `\g<2>` 等同于 `\2`,但在诸如 `\g<2>0` 之类的替换字符串中并不模糊。 (`\20` 将被解释为对组 20 的引用,而不是对组 2 的引用,后跟字面字符 `'0'`。) 以下替换都是等效的,但使用所有三种变体替换字符串。:
```
>>> p = re.compile('section{ (?P<name> [^}]* ) }', re.VERBOSE)
>>> p.sub(r'subsection{\1}','section{First}')
'subsection{First}'
>>> p.sub(r'subsection{\g<1>}','section{First}')
'subsection{First}'
>>> p.sub(r'subsection{\g<name>}','section{First}')
'subsection{First}'
```
*replacement* 也可以是一个函数,它可以为你提供更多控制。 如果 *replacement* 是一个函数,则为 *pattern* 的每次非重叠出现将调用该函数。 在每次调用时,函数都会传递一个匹配的 [匹配对象](../library/re.xhtml#match-objects) 参数,并可以使用此信息计算所需的替换字符串并将其返回。
在以下示例中,替换函数将小数转换为十六进制:
```
>>> def hexrepl(match):
... "Return the hex string for a decimal number"
... value = int(match.group())
... return hex(value)
...
>>> p = re.compile(r'\d+')
>>> p.sub(hexrepl, 'Call 65490 for printing, 49152 for user code.')
'Call 0xffd2 for printing, 0xc000 for user code.'
```
使用模块级别 [`re.sub()`](../library/re.xhtml#re.sub "re.sub") 函数时,模式作为第一个参数传递。 图案可以作为对象或字符串提供;如果需要指定正则表达式标志,则必须使用模式对象作为第一个参数,或者在模式字符串中使用嵌入式修饰符,例如: `sub("(?i)b+", "x", "bbbb BBBB")` 返回 `'x x'`。
## 常见问题
正则表达式对于某些应用程序来说是一个强大的工具,但在某些方面,它们的行为并不直观,有时它们的行为方式与你的预期不同。 本节将指出一些最常见的陷阱。
### 使用字符串方法
有时使用 [`re`](../library/re.xhtml#module-re "re: Regular expression operations.") 模块是一个错误。 如果你匹配固定字符串或单个字符类,并且你没有使用任何 [`re`](../library/re.xhtml#module-re "re: Regular expression operations.") 功能,例如 [`IGNORECASE`](../library/re.xhtml#re.IGNORECASE "re.IGNORECASE") 标志,那么正则表达式的全部功能可能不是必需的。 字符串有几种方法可以使用固定字符串执行操作,它们通常要快得多,因为实现是一个针对此目的而优化的单个小 C 循环,而不是大型、更通用的正则表达式引擎。
一个例子可能是用另一个固定字符串替换一个固定字符串;例如,你可以用 `deed` 替换 `word` 。 [`re.sub()`](../library/re.xhtml#re.sub "re.sub") 看起来像是用于此的函数,但请考虑 [`replace()`](../library/stdtypes.xhtml#str.replace "str.replace") 方法。 注意 `replace()` 也会替换单词里面的 `word` ,把 `swordfish` 变成 `sdeedfish` ,但简单的正则 `word` 也会这样做。 (为了避免对单词的部分进行替换,模式必须是 `\bword\b`,以便要求 `word` 在任何一方都有一个单词边界。这使得工作超出了 `replace()` 的能力。)
另一个常见任务是从字符串中删除单个字符的每个匹配项或将其替换为另一个字符。 你可以用 `re.sub('\n', ' ', S)` 之类的东西来做这件事,但是 [`translate()`](../library/stdtypes.xhtml#str.translate "str.translate") 能够完成这两项任务,并且比任何正则表达式都快。
简而言之,在转向 [`re`](../library/re.xhtml#module-re "re: Regular expression operations.") 模块之前,请考虑是否可以使用更快更简单的字符串方法解决问题。
### match() 和 search()
The [`match()`](../library/re.xhtml#re.match "re.match") function only checks if the RE matches at the beginning of the string while [`search()`](../library/re.xhtml#re.search "re.search") will scan forward through the string for a match. It's important to keep this distinction in mind. Remember, `match()` will only report a successful match which will start at 0; if the match wouldn't start at zero, `match()` will *not* report it.
```
>>> print(re.match('super', 'superstition').span())
(0, 5)
>>> print(re.match('super', 'insuperable'))
None
```
另一方面, [`search()`](../library/re.xhtml#re.search "re.search") 将向前扫描字符串,报告它找到的第一个匹配项。:
```
>>> print(re.search('super', 'superstition').span())
(0, 5)
>>> print(re.search('super', 'insuperable').span())
(2, 7)
```
有时你会被诱惑继续使用 [`re.match()`](../library/re.xhtml#re.match "re.match") ,只需在你的正则前面添加 `.*` 。抵制这种诱惑并使用 [`re.search()`](../library/re.xhtml#re.search "re.search") 代替。 正则表达式编译器对正则进行一些分析,以加快寻找匹配的过程。 其中一个分析可以确定匹配的第一个特征必须是什么;例如,以 `Crow` 开头的模式必须与 `'C'` 匹配。 分析让引擎快速扫描字符串,寻找起始字符,只在找到 `'C'` 时尝试完全匹配。
添加 `.*` 会使这个优化失效,需要扫描到字符串的末尾,然后回溯以找到正则的其余部分的匹配。 使用 [`re.search()`](../library/re.xhtml#re.search "re.search") 代替。
### 贪婪与非贪婪
当重复一个正则表达式时,就像在 `a*` 中一样,最终的动作就是消耗尽可能多的模式。 当你尝试匹配一对对称分隔符,例如 HTML 标记周围的尖括号时,这个事实经常会让你感到困惑。因为 `.*` 的贪婪性质, 用于匹配单个 HTML 标记的简单模式不起作用。
```
>>> s = '<html><head><title>Title</title>'
>>> len(s)
32
>>> print(re.match('<.*>', s).span())
(0, 32)
>>> print(re.match('<.*>', s).group())
<html><head><title>Title</title>
```
正则匹配 `'<'` 中的 `'<html>'` 和 `.*` 消耗字符串的其余部分。 正则中还有更多的剩余东西,并且 `>` 在字符串的末尾不能匹配,所以正则表达式引擎必须逐个字符地回溯,直到它找到匹配 `>` 。最终匹配从 `'<html>'` 中的 `'<'` 扩展到 `'</title>'` 中的 `'>'` ,而这并不是你想要的结果。
在这种情况下,解决方案是使用非贪婪的限定符 `*?` 、 `+?` 、 `??` 或 `{m,n}?` ,匹配为尽可能 *少* 的文字。 在上面的例子中,在第一次 `'<'` 匹配后立即尝试 `'>'` ,当它失败时,引擎一次前进一个字符,每一步都重试 `'>'` 。 这产生了正确的结果:
```
>>> print(re.match('<.*?>', s).group())
<html>
```
(请注意,使用正则表达式解析 HTML 或 XML 很痛苦。快而脏的模式将处理常见情况,但 HTML 和 XML 有特殊情况会破坏明显的正则表达式;当你编写正则表达式处理所有可能的情况时,模式将非常复杂。使用 HTML 或 XML 解析器模块来执行此类任务。)
### 使用 re.VERBOSE
到目前为止,你可能已经注意到正则表达式是一种非常紧凑的表示法,但它们并不是非常易读。 具有中等复杂度的正则可能会成为反斜杠、括号和元字符的冗长集合,使其难以阅读和理解。
对于这样的正则,在编译正则表达式时指定 [`re.VERBOSE`](../library/re.xhtml#re.VERBOSE "re.VERBOSE") 标志可能会有所帮助,因为它允许你更清楚地格式化正则表达式。
`re.VERBOSE` 标志有几种效果。 正则表达式中的 *不是* 在字符类中的空格将被忽略。 这意味着表达式如 `dog | cat` 等同于不太可读的 `dog|cat` ,但 `[a b]` 仍将匹配字符 `'a'` 、 `'b'` 或空格。 此外,你还可以在正则中放置注释;注释从 `#` 字符扩展到下一个换行符。 当与三引号字符串一起使用时,这使正则的格式更加整齐:
```
pat = re.compile(r"""
\s* # Skip leading whitespace
(?P<header>[^:]+) # Header name
\s* : # Whitespace, and a colon
(?P<value>.*?) # The header's value -- *? used to
# lose the following trailing whitespace
\s*$ # Trailing whitespace to end-of-line
""", re.VERBOSE)
```
这更具有可读性:
```
pat = re.compile(r"\s*(?P<header>[^:]+)\s*:(?P<value>.*?)\s*$")
```
## 反馈
正则表达式是一个复杂的主题。 这份文档是否有助于你理解它们? 是否存在不清楚的部分,或者你遇到的问题未在此处涉及? 如果是,请向作者发送改进建议。
关于正则表达式的最完整的书几乎肯定是由 O'Reilly 出版的 Jeffrey Friedl 的 Mastering Regular Expressions 。 不幸的是,它专注于 Perl 和 Java 的正则表达式,并且根本不包含任何 Python 材料,因此它不能用作 Python 编程的参考。 (第一版涵盖了 Python 现在删除的 `regex` 模块,这对你没有多大帮助。)考虑从你的图书馆中查找它。
### 导航
- [索引](../genindex.xhtml "总目录")
- [模块](../py-modindex.xhtml "Python 模块索引") |
- [下一页](sockets.xhtml "套接字编程指南") |
- [上一页](logging-cookbook.xhtml "日志操作手册") |
- 
- [Python](https://www.python.org/) »
- zh\_CN 3.7.3 [文档](../index.xhtml) »
- [Python 常用指引](index.xhtml) »
- $('.inline-search').show(0); |
© [版权所有](../copyright.xhtml) 2001-2019, Python Software Foundation.
Python 软件基金会是一个非盈利组织。 [请捐助。](https://www.python.org/psf/donations/)
最后更新于 5月 21, 2019. [发现了问题](../bugs.xhtml)?
使用[Sphinx](http://sphinx.pocoo.org/)1.8.4 创建。
- Python文档内容
- Python 有什么新变化?
- Python 3.7 有什么新变化
- 摘要 - 发布重点
- 新的特性
- 其他语言特性修改
- 新增模块
- 改进的模块
- C API 的改变
- 构建的改变
- 性能优化
- 其他 CPython 实现的改变
- 已弃用的 Python 行为
- 已弃用的 Python 模块、函数和方法
- 已弃用的 C API 函数和类型
- 平台支持的移除
- API 与特性的移除
- 移除的模块
- Windows 专属的改变
- 移植到 Python 3.7
- Python 3.7.1 中的重要变化
- Python 3.7.2 中的重要变化
- Python 3.6 有什么新变化A
- 摘要 - 发布重点
- 新的特性
- 其他语言特性修改
- 新增模块
- 改进的模块
- 性能优化
- Build and C API Changes
- 其他改进
- 弃用
- 移除
- 移植到Python 3.6
- Python 3.6.2 中的重要变化
- Python 3.6.4 中的重要变化
- Python 3.6.5 中的重要变化
- Python 3.6.7 中的重要变化
- Python 3.5 有什么新变化
- 摘要 - 发布重点
- 新的特性
- 其他语言特性修改
- 新增模块
- 改进的模块
- Other module-level changes
- 性能优化
- Build and C API Changes
- 弃用
- 移除
- Porting to Python 3.5
- Notable changes in Python 3.5.4
- What's New In Python 3.4
- 摘要 - 发布重点
- 新的特性
- 新增模块
- 改进的模块
- CPython Implementation Changes
- 弃用
- 移除
- Porting to Python 3.4
- Changed in 3.4.3
- What's New In Python 3.3
- 摘要 - 发布重点
- PEP 405: Virtual Environments
- PEP 420: Implicit Namespace Packages
- PEP 3118: New memoryview implementation and buffer protocol documentation
- PEP 393: Flexible String Representation
- PEP 397: Python Launcher for Windows
- PEP 3151: Reworking the OS and IO exception hierarchy
- PEP 380: Syntax for Delegating to a Subgenerator
- PEP 409: Suppressing exception context
- PEP 414: Explicit Unicode literals
- PEP 3155: Qualified name for classes and functions
- PEP 412: Key-Sharing Dictionary
- PEP 362: Function Signature Object
- PEP 421: Adding sys.implementation
- Using importlib as the Implementation of Import
- 其他语言特性修改
- A Finer-Grained Import Lock
- Builtin functions and types
- 新增模块
- 改进的模块
- 性能优化
- Build and C API Changes
- 弃用
- Porting to Python 3.3
- What's New In Python 3.2
- PEP 384: Defining a Stable ABI
- PEP 389: Argparse Command Line Parsing Module
- PEP 391: Dictionary Based Configuration for Logging
- PEP 3148: The concurrent.futures module
- PEP 3147: PYC Repository Directories
- PEP 3149: ABI Version Tagged .so Files
- PEP 3333: Python Web Server Gateway Interface v1.0.1
- 其他语言特性修改
- New, Improved, and Deprecated Modules
- 多线程
- 性能优化
- Unicode
- Codecs
- 文档
- IDLE
- Code Repository
- Build and C API Changes
- Porting to Python 3.2
- What's New In Python 3.1
- PEP 372: Ordered Dictionaries
- PEP 378: Format Specifier for Thousands Separator
- 其他语言特性修改
- New, Improved, and Deprecated Modules
- 性能优化
- IDLE
- Build and C API Changes
- Porting to Python 3.1
- What's New In Python 3.0
- Common Stumbling Blocks
- Overview Of Syntax Changes
- Changes Already Present In Python 2.6
- Library Changes
- PEP 3101: A New Approach To String Formatting
- Changes To Exceptions
- Miscellaneous Other Changes
- Build and C API Changes
- 性能
- Porting To Python 3.0
- What's New in Python 2.7
- The Future for Python 2.x
- Changes to the Handling of Deprecation Warnings
- Python 3.1 Features
- PEP 372: Adding an Ordered Dictionary to collections
- PEP 378: Format Specifier for Thousands Separator
- PEP 389: The argparse Module for Parsing Command Lines
- PEP 391: Dictionary-Based Configuration For Logging
- PEP 3106: Dictionary Views
- PEP 3137: The memoryview Object
- 其他语言特性修改
- New and Improved Modules
- Build and C API Changes
- Other Changes and Fixes
- Porting to Python 2.7
- New Features Added to Python 2.7 Maintenance Releases
- Acknowledgements
- Python 2.6 有什么新变化
- Python 3.0
- Changes to the Development Process
- PEP 343: The 'with' statement
- PEP 366: Explicit Relative Imports From a Main Module
- PEP 370: Per-user site-packages Directory
- PEP 371: The multiprocessing Package
- PEP 3101: Advanced String Formatting
- PEP 3105: print As a Function
- PEP 3110: Exception-Handling Changes
- PEP 3112: Byte Literals
- PEP 3116: New I/O Library
- PEP 3118: Revised Buffer Protocol
- PEP 3119: Abstract Base Classes
- PEP 3127: Integer Literal Support and Syntax
- PEP 3129: Class Decorators
- PEP 3141: A Type Hierarchy for Numbers
- 其他语言特性修改
- New and Improved Modules
- Deprecations and Removals
- Build and C API Changes
- Porting to Python 2.6
- Acknowledgements
- What's New in Python 2.5
- PEP 308: Conditional Expressions
- PEP 309: Partial Function Application
- PEP 314: Metadata for Python Software Packages v1.1
- PEP 328: Absolute and Relative Imports
- PEP 338: Executing Modules as Scripts
- PEP 341: Unified try/except/finally
- PEP 342: New Generator Features
- PEP 343: The 'with' statement
- PEP 352: Exceptions as New-Style Classes
- PEP 353: Using ssize_t as the index type
- PEP 357: The 'index' method
- 其他语言特性修改
- New, Improved, and Removed Modules
- Build and C API Changes
- Porting to Python 2.5
- Acknowledgements
- What's New in Python 2.4
- PEP 218: Built-In Set Objects
- PEP 237: Unifying Long Integers and Integers
- PEP 289: Generator Expressions
- PEP 292: Simpler String Substitutions
- PEP 318: Decorators for Functions and Methods
- PEP 322: Reverse Iteration
- PEP 324: New subprocess Module
- PEP 327: Decimal Data Type
- PEP 328: Multi-line Imports
- PEP 331: Locale-Independent Float/String Conversions
- 其他语言特性修改
- New, Improved, and Deprecated Modules
- Build and C API Changes
- Porting to Python 2.4
- Acknowledgements
- What's New in Python 2.3
- PEP 218: A Standard Set Datatype
- PEP 255: Simple Generators
- PEP 263: Source Code Encodings
- PEP 273: Importing Modules from ZIP Archives
- PEP 277: Unicode file name support for Windows NT
- PEP 278: Universal Newline Support
- PEP 279: enumerate()
- PEP 282: The logging Package
- PEP 285: A Boolean Type
- PEP 293: Codec Error Handling Callbacks
- PEP 301: Package Index and Metadata for Distutils
- PEP 302: New Import Hooks
- PEP 305: Comma-separated Files
- PEP 307: Pickle Enhancements
- Extended Slices
- 其他语言特性修改
- New, Improved, and Deprecated Modules
- Pymalloc: A Specialized Object Allocator
- Build and C API Changes
- Other Changes and Fixes
- Porting to Python 2.3
- Acknowledgements
- What's New in Python 2.2
- 概述
- PEPs 252 and 253: Type and Class Changes
- PEP 234: Iterators
- PEP 255: Simple Generators
- PEP 237: Unifying Long Integers and Integers
- PEP 238: Changing the Division Operator
- Unicode Changes
- PEP 227: Nested Scopes
- New and Improved Modules
- Interpreter Changes and Fixes
- Other Changes and Fixes
- Acknowledgements
- What's New in Python 2.1
- 概述
- PEP 227: Nested Scopes
- PEP 236: future Directives
- PEP 207: Rich Comparisons
- PEP 230: Warning Framework
- PEP 229: New Build System
- PEP 205: Weak References
- PEP 232: Function Attributes
- PEP 235: Importing Modules on Case-Insensitive Platforms
- PEP 217: Interactive Display Hook
- PEP 208: New Coercion Model
- PEP 241: Metadata in Python Packages
- New and Improved Modules
- Other Changes and Fixes
- Acknowledgements
- What's New in Python 2.0
- 概述
- What About Python 1.6?
- New Development Process
- Unicode
- 列表推导式
- Augmented Assignment
- 字符串的方法
- Garbage Collection of Cycles
- Other Core Changes
- Porting to 2.0
- Extending/Embedding Changes
- Distutils: Making Modules Easy to Install
- XML Modules
- Module changes
- New modules
- IDLE Improvements
- Deleted and Deprecated Modules
- Acknowledgements
- 更新日志
- Python 下一版
- Python 3.7.3 最终版
- Python 3.7.3 发布候选版 1
- Python 3.7.2 最终版
- Python 3.7.2 发布候选版 1
- Python 3.7.1 最终版
- Python 3.7.1 RC 2版本
- Python 3.7.1 发布候选版 1
- Python 3.7.0 正式版
- Python 3.7.0 release candidate 1
- Python 3.7.0 beta 5
- Python 3.7.0 beta 4
- Python 3.7.0 beta 3
- Python 3.7.0 beta 2
- Python 3.7.0 beta 1
- Python 3.7.0 alpha 4
- Python 3.7.0 alpha 3
- Python 3.7.0 alpha 2
- Python 3.7.0 alpha 1
- Python 3.6.6 final
- Python 3.6.6 RC 1
- Python 3.6.5 final
- Python 3.6.5 release candidate 1
- Python 3.6.4 final
- Python 3.6.4 release candidate 1
- Python 3.6.3 final
- Python 3.6.3 release candidate 1
- Python 3.6.2 final
- Python 3.6.2 release candidate 2
- Python 3.6.2 release candidate 1
- Python 3.6.1 final
- Python 3.6.1 release candidate 1
- Python 3.6.0 final
- Python 3.6.0 release candidate 2
- Python 3.6.0 release candidate 1
- Python 3.6.0 beta 4
- Python 3.6.0 beta 3
- Python 3.6.0 beta 2
- Python 3.6.0 beta 1
- Python 3.6.0 alpha 4
- Python 3.6.0 alpha 3
- Python 3.6.0 alpha 2
- Python 3.6.0 alpha 1
- Python 3.5.5 final
- Python 3.5.5 release candidate 1
- Python 3.5.4 final
- Python 3.5.4 release candidate 1
- Python 3.5.3 final
- Python 3.5.3 release candidate 1
- Python 3.5.2 final
- Python 3.5.2 release candidate 1
- Python 3.5.1 final
- Python 3.5.1 release candidate 1
- Python 3.5.0 final
- Python 3.5.0 release candidate 4
- Python 3.5.0 release candidate 3
- Python 3.5.0 release candidate 2
- Python 3.5.0 release candidate 1
- Python 3.5.0 beta 4
- Python 3.5.0 beta 3
- Python 3.5.0 beta 2
- Python 3.5.0 beta 1
- Python 3.5.0 alpha 4
- Python 3.5.0 alpha 3
- Python 3.5.0 alpha 2
- Python 3.5.0 alpha 1
- Python 教程
- 课前甜点
- 使用 Python 解释器
- 调用解释器
- 解释器的运行环境
- Python 的非正式介绍
- Python 作为计算器使用
- 走向编程的第一步
- 其他流程控制工具
- if 语句
- for 语句
- range() 函数
- break 和 continue 语句,以及循环中的 else 子句
- pass 语句
- 定义函数
- 函数定义的更多形式
- 小插曲:编码风格
- 数据结构
- 列表的更多特性
- del 语句
- 元组和序列
- 集合
- 字典
- 循环的技巧
- 深入条件控制
- 序列和其它类型的比较
- 模块
- 有关模块的更多信息
- 标准模块
- dir() 函数
- 包
- 输入输出
- 更漂亮的输出格式
- 读写文件
- 错误和异常
- 语法错误
- 异常
- 处理异常
- 抛出异常
- 用户自定义异常
- 定义清理操作
- 预定义的清理操作
- 类
- 名称和对象
- Python 作用域和命名空间
- 初探类
- 补充说明
- 继承
- 私有变量
- 杂项说明
- 迭代器
- 生成器
- 生成器表达式
- 标准库简介
- 操作系统接口
- 文件通配符
- 命令行参数
- 错误输出重定向和程序终止
- 字符串模式匹配
- 数学
- 互联网访问
- 日期和时间
- 数据压缩
- 性能测量
- 质量控制
- 自带电池
- 标准库简介 —— 第二部分
- 格式化输出
- 模板
- 使用二进制数据记录格式
- 多线程
- 日志
- 弱引用
- 用于操作列表的工具
- 十进制浮点运算
- 虚拟环境和包
- 概述
- 创建虚拟环境
- 使用pip管理包
- 接下来?
- 交互式编辑和编辑历史
- Tab 补全和编辑历史
- 默认交互式解释器的替代品
- 浮点算术:争议和限制
- 表示性错误
- 附录
- 交互模式
- 安装和使用 Python
- 命令行与环境
- 命令行
- 环境变量
- 在Unix平台中使用Python
- 获取最新版本的Python
- 构建Python
- 与Python相关的路径和文件
- 杂项
- 编辑器和集成开发环境
- 在Windows上使用 Python
- 完整安装程序
- Microsoft Store包
- nuget.org 安装包
- 可嵌入的包
- 替代捆绑包
- 配置Python
- 适用于Windows的Python启动器
- 查找模块
- 附加模块
- 在Windows上编译Python
- 其他平台
- 在苹果系统上使用 Python
- 获取和安装 MacPython
- IDE
- 安装额外的 Python 包
- Mac 上的图形界面编程
- 在 Mac 上分发 Python 应用程序
- 其他资源
- Python 语言参考
- 概述
- 其他实现
- 标注
- 词法分析
- 行结构
- 其他形符
- 标识符和关键字
- 字面值
- 运算符
- 分隔符
- 数据模型
- 对象、值与类型
- 标准类型层级结构
- 特殊方法名称
- 协程
- 执行模型
- 程序的结构
- 命名与绑定
- 异常
- 导入系统
- importlib
- 包
- 搜索
- 加载
- 基于路径的查找器
- 替换标准导入系统
- Package Relative Imports
- 有关 main 的特殊事项
- 开放问题项
- 参考文献
- 表达式
- 算术转换
- 原子
- 原型
- await 表达式
- 幂运算符
- 一元算术和位运算
- 二元算术运算符
- 移位运算
- 二元位运算
- 比较运算
- 布尔运算
- 条件表达式
- lambda 表达式
- 表达式列表
- 求值顺序
- 运算符优先级
- 简单语句
- 表达式语句
- 赋值语句
- assert 语句
- pass 语句
- del 语句
- return 语句
- yield 语句
- raise 语句
- break 语句
- continue 语句
- import 语句
- global 语句
- nonlocal 语句
- 复合语句
- if 语句
- while 语句
- for 语句
- try 语句
- with 语句
- 函数定义
- 类定义
- 协程
- 最高层级组件
- 完整的 Python 程序
- 文件输入
- 交互式输入
- 表达式输入
- 完整的语法规范
- Python 标准库
- 概述
- 可用性注释
- 内置函数
- 内置常量
- 由 site 模块添加的常量
- 内置类型
- 逻辑值检测
- 布尔运算 — and, or, not
- 比较
- 数字类型 — int, float, complex
- 迭代器类型
- 序列类型 — list, tuple, range
- 文本序列类型 — str
- 二进制序列类型 — bytes, bytearray, memoryview
- 集合类型 — set, frozenset
- 映射类型 — dict
- 上下文管理器类型
- 其他内置类型
- 特殊属性
- 内置异常
- 基类
- 具体异常
- 警告
- 异常层次结构
- 文本处理服务
- string — 常见的字符串操作
- re — 正则表达式操作
- 模块 difflib 是一个计算差异的助手
- textwrap — Text wrapping and filling
- unicodedata — Unicode 数据库
- stringprep — Internet String Preparation
- readline — GNU readline interface
- rlcompleter — GNU readline的完成函数
- 二进制数据服务
- struct — Interpret bytes as packed binary data
- codecs — Codec registry and base classes
- 数据类型
- datetime — 基础日期/时间数据类型
- calendar — General calendar-related functions
- collections — 容器数据类型
- collections.abc — 容器的抽象基类
- heapq — 堆队列算法
- bisect — Array bisection algorithm
- array — Efficient arrays of numeric values
- weakref — 弱引用
- types — Dynamic type creation and names for built-in types
- copy — 浅层 (shallow) 和深层 (deep) 复制操作
- pprint — 数据美化输出
- reprlib — Alternate repr() implementation
- enum — Support for enumerations
- 数字和数学模块
- numbers — 数字的抽象基类
- math — 数学函数
- cmath — Mathematical functions for complex numbers
- decimal — 十进制定点和浮点运算
- fractions — 分数
- random — 生成伪随机数
- statistics — Mathematical statistics functions
- 函数式编程模块
- itertools — 为高效循环而创建迭代器的函数
- functools — 高阶函数和可调用对象上的操作
- operator — 标准运算符替代函数
- 文件和目录访问
- pathlib — 面向对象的文件系统路径
- os.path — 常见路径操作
- fileinput — Iterate over lines from multiple input streams
- stat — Interpreting stat() results
- filecmp — File and Directory Comparisons
- tempfile — Generate temporary files and directories
- glob — Unix style pathname pattern expansion
- fnmatch — Unix filename pattern matching
- linecache — Random access to text lines
- shutil — High-level file operations
- macpath — Mac OS 9 路径操作函数
- 数据持久化
- pickle —— Python 对象序列化
- copyreg — Register pickle support functions
- shelve — Python object persistence
- marshal — Internal Python object serialization
- dbm — Interfaces to Unix “databases”
- sqlite3 — SQLite 数据库 DB-API 2.0 接口模块
- 数据压缩和存档
- zlib — 与 gzip 兼容的压缩
- gzip — 对 gzip 格式的支持
- bz2 — 对 bzip2 压缩算法的支持
- lzma — 用 LZMA 算法压缩
- zipfile — 在 ZIP 归档中工作
- tarfile — Read and write tar archive files
- 文件格式
- csv — CSV 文件读写
- configparser — Configuration file parser
- netrc — netrc file processing
- xdrlib — Encode and decode XDR data
- plistlib — Generate and parse Mac OS X .plist files
- 加密服务
- hashlib — 安全哈希与消息摘要
- hmac — 基于密钥的消息验证
- secrets — Generate secure random numbers for managing secrets
- 通用操作系统服务
- os — 操作系统接口模块
- io — 处理流的核心工具
- time — 时间的访问和转换
- argparse — 命令行选项、参数和子命令解析器
- getopt — C-style parser for command line options
- 模块 logging — Python 的日志记录工具
- logging.config — 日志记录配置
- logging.handlers — Logging handlers
- getpass — 便携式密码输入工具
- curses — 终端字符单元显示的处理
- curses.textpad — Text input widget for curses programs
- curses.ascii — Utilities for ASCII characters
- curses.panel — A panel stack extension for curses
- platform — Access to underlying platform's identifying data
- errno — Standard errno system symbols
- ctypes — Python 的外部函数库
- 并发执行
- threading — 基于线程的并行
- multiprocessing — 基于进程的并行
- concurrent 包
- concurrent.futures — 启动并行任务
- subprocess — 子进程管理
- sched — 事件调度器
- queue — 一个同步的队列类
- _thread — 底层多线程 API
- _dummy_thread — _thread 的替代模块
- dummy_threading — 可直接替代 threading 模块。
- contextvars — Context Variables
- Context Variables
- Manual Context Management
- asyncio support
- 网络和进程间通信
- asyncio — 异步 I/O
- socket — 底层网络接口
- ssl — TLS/SSL wrapper for socket objects
- select — Waiting for I/O completion
- selectors — 高级 I/O 复用库
- asyncore — 异步socket处理器
- asynchat — 异步 socket 指令/响应 处理器
- signal — Set handlers for asynchronous events
- mmap — Memory-mapped file support
- 互联网数据处理
- email — 电子邮件与 MIME 处理包
- json — JSON 编码和解码器
- mailcap — Mailcap file handling
- mailbox — Manipulate mailboxes in various formats
- mimetypes — Map filenames to MIME types
- base64 — Base16, Base32, Base64, Base85 数据编码
- binhex — 对binhex4文件进行编码和解码
- binascii — 二进制和 ASCII 码互转
- quopri — Encode and decode MIME quoted-printable data
- uu — Encode and decode uuencode files
- 结构化标记处理工具
- html — 超文本标记语言支持
- html.parser — 简单的 HTML 和 XHTML 解析器
- html.entities — HTML 一般实体的定义
- XML处理模块
- xml.etree.ElementTree — The ElementTree XML API
- xml.dom — The Document Object Model API
- xml.dom.minidom — Minimal DOM implementation
- xml.dom.pulldom — Support for building partial DOM trees
- xml.sax — Support for SAX2 parsers
- xml.sax.handler — Base classes for SAX handlers
- xml.sax.saxutils — SAX Utilities
- xml.sax.xmlreader — Interface for XML parsers
- xml.parsers.expat — Fast XML parsing using Expat
- 互联网协议和支持
- webbrowser — 方便的Web浏览器控制器
- cgi — Common Gateway Interface support
- cgitb — Traceback manager for CGI scripts
- wsgiref — WSGI Utilities and Reference Implementation
- urllib — URL 处理模块
- urllib.request — 用于打开 URL 的可扩展库
- urllib.response — Response classes used by urllib
- urllib.parse — Parse URLs into components
- urllib.error — Exception classes raised by urllib.request
- urllib.robotparser — Parser for robots.txt
- http — HTTP 模块
- http.client — HTTP协议客户端
- ftplib — FTP protocol client
- poplib — POP3 protocol client
- imaplib — IMAP4 protocol client
- nntplib — NNTP protocol client
- smtplib —SMTP协议客户端
- smtpd — SMTP Server
- telnetlib — Telnet client
- uuid — UUID objects according to RFC 4122
- socketserver — A framework for network servers
- http.server — HTTP 服务器
- http.cookies — HTTP state management
- http.cookiejar — Cookie handling for HTTP clients
- xmlrpc — XMLRPC 服务端与客户端模块
- xmlrpc.client — XML-RPC client access
- xmlrpc.server — Basic XML-RPC servers
- ipaddress — IPv4/IPv6 manipulation library
- 多媒体服务
- audioop — Manipulate raw audio data
- aifc — Read and write AIFF and AIFC files
- sunau — 读写 Sun AU 文件
- wave — 读写WAV格式文件
- chunk — Read IFF chunked data
- colorsys — Conversions between color systems
- imghdr — 推测图像类型
- sndhdr — 推测声音文件的类型
- ossaudiodev — Access to OSS-compatible audio devices
- 国际化
- gettext — 多语种国际化服务
- locale — 国际化服务
- 程序框架
- turtle — 海龟绘图
- cmd — 支持面向行的命令解释器
- shlex — Simple lexical analysis
- Tk图形用户界面(GUI)
- tkinter — Tcl/Tk的Python接口
- tkinter.ttk — Tk themed widgets
- tkinter.tix — Extension widgets for Tk
- tkinter.scrolledtext — 滚动文字控件
- IDLE
- 其他图形用户界面(GUI)包
- 开发工具
- typing — 类型标注支持
- pydoc — Documentation generator and online help system
- doctest — Test interactive Python examples
- unittest — 单元测试框架
- unittest.mock — mock object library
- unittest.mock 上手指南
- 2to3 - 自动将 Python 2 代码转为 Python 3 代码
- test — Regression tests package for Python
- test.support — Utilities for the Python test suite
- test.support.script_helper — Utilities for the Python execution tests
- 调试和分析
- bdb — Debugger framework
- faulthandler — Dump the Python traceback
- pdb — The Python Debugger
- The Python Profilers
- timeit — 测量小代码片段的执行时间
- trace — Trace or track Python statement execution
- tracemalloc — Trace memory allocations
- 软件打包和分发
- distutils — 构建和安装 Python 模块
- ensurepip — Bootstrapping the pip installer
- venv — 创建虚拟环境
- zipapp — Manage executable Python zip archives
- Python运行时服务
- sys — 系统相关的参数和函数
- sysconfig — Provide access to Python's configuration information
- builtins — 内建对象
- main — 顶层脚本环境
- warnings — Warning control
- dataclasses — 数据类
- contextlib — Utilities for with-statement contexts
- abc — 抽象基类
- atexit — 退出处理器
- traceback — Print or retrieve a stack traceback
- future — Future 语句定义
- gc — 垃圾回收器接口
- inspect — 检查对象
- site — Site-specific configuration hook
- 自定义 Python 解释器
- code — Interpreter base classes
- codeop — Compile Python code
- 导入模块
- zipimport — Import modules from Zip archives
- pkgutil — Package extension utility
- modulefinder — 查找脚本使用的模块
- runpy — Locating and executing Python modules
- importlib — The implementation of import
- Python 语言服务
- parser — Access Python parse trees
- ast — 抽象语法树
- symtable — Access to the compiler's symbol tables
- symbol — 与 Python 解析树一起使用的常量
- token — 与Python解析树一起使用的常量
- keyword — 检验Python关键字
- tokenize — Tokenizer for Python source
- tabnanny — 模糊缩进检测
- pyclbr — Python class browser support
- py_compile — Compile Python source files
- compileall — Byte-compile Python libraries
- dis — Python 字节码反汇编器
- pickletools — Tools for pickle developers
- 杂项服务
- formatter — Generic output formatting
- Windows系统相关模块
- msilib — Read and write Microsoft Installer files
- msvcrt — Useful routines from the MS VC++ runtime
- winreg — Windows 注册表访问
- winsound — Sound-playing interface for Windows
- Unix 专有服务
- posix — The most common POSIX system calls
- pwd — 用户密码数据库
- spwd — The shadow password database
- grp — The group database
- crypt — Function to check Unix passwords
- termios — POSIX style tty control
- tty — 终端控制功能
- pty — Pseudo-terminal utilities
- fcntl — The fcntl and ioctl system calls
- pipes — Interface to shell pipelines
- resource — Resource usage information
- nis — Interface to Sun's NIS (Yellow Pages)
- Unix syslog 库例程
- 被取代的模块
- optparse — Parser for command line options
- imp — Access the import internals
- 未创建文档的模块
- 平台特定模块
- 扩展和嵌入 Python 解释器
- 推荐的第三方工具
- 不使用第三方工具创建扩展
- 使用 C 或 C++ 扩展 Python
- 自定义扩展类型:教程
- 定义扩展类型:已分类主题
- 构建C/C++扩展
- 在Windows平台编译C和C++扩展
- 在更大的应用程序中嵌入 CPython 运行时
- Embedding Python in Another Application
- Python/C API 参考手册
- 概述
- 代码标准
- 包含文件
- 有用的宏
- 对象、类型和引用计数
- 异常
- 嵌入Python
- 调试构建
- 稳定的应用程序二进制接口
- The Very High Level Layer
- Reference Counting
- 异常处理
- Printing and clearing
- 抛出异常
- Issuing warnings
- Querying the error indicator
- Signal Handling
- Exception Classes
- Exception Objects
- Unicode Exception Objects
- Recursion Control
- 标准异常
- 标准警告类别
- 工具
- 操作系统实用程序
- 系统功能
- 过程控制
- 导入模块
- Data marshalling support
- 语句解释及变量编译
- 字符串转换与格式化
- 反射
- 编解码器注册与支持功能
- 抽象对象层
- Object Protocol
- 数字协议
- Sequence Protocol
- Mapping Protocol
- 迭代器协议
- 缓冲协议
- Old Buffer Protocol
- 具体的对象层
- 基本对象
- 数值对象
- 序列对象
- 容器对象
- 函数对象
- 其他对象
- Initialization, Finalization, and Threads
- 在Python初始化之前
- 全局配置变量
- Initializing and finalizing the interpreter
- Process-wide parameters
- Thread State and the Global Interpreter Lock
- Sub-interpreter support
- Asynchronous Notifications
- Profiling and Tracing
- Advanced Debugger Support
- Thread Local Storage Support
- 内存管理
- 概述
- 原始内存接口
- Memory Interface
- 对象分配器
- 默认内存分配器
- Customize Memory Allocators
- The pymalloc allocator
- tracemalloc C API
- 示例
- 对象实现支持
- 在堆中分配对象
- Common Object Structures
- Type 对象
- Number Object Structures
- Mapping Object Structures
- Sequence Object Structures
- Buffer Object Structures
- Async Object Structures
- 使对象类型支持循环垃圾回收
- API 和 ABI 版本管理
- 分发 Python 模块
- 关键术语
- 开源许可与协作
- 安装工具
- 阅读指南
- 我该如何...?
- ...为我的项目选择一个名字?
- ...创建和分发二进制扩展?
- 安装 Python 模块
- 关键术语
- 基本使用
- 我应如何 ...?
- ... 在 Python 3.4 之前的 Python 版本中安装 pip ?
- ... 只为当前用户安装软件包?
- ... 安装科学计算类 Python 软件包?
- ... 使用并行安装的多个 Python 版本?
- 常见的安装问题
- 在 Linux 的系统 Python 版本上安装
- 未安装 pip
- 安装二进制编译扩展
- Python 常用指引
- 将 Python 2 代码迁移到 Python 3
- 简要说明
- 详情
- 将扩展模块移植到 Python 3
- 条件编译
- 对象API的更改
- 模块初始化和状态
- CObject 替换为 Capsule
- 其他选项
- Curses Programming with Python
- What is curses?
- Starting and ending a curses application
- Windows and Pads
- Displaying Text
- User Input
- For More Information
- 实现描述器
- 摘要
- 定义和简介
- 描述器协议
- 发起调用描述符
- 描述符示例
- Properties
- 函数和方法
- Static Methods and Class Methods
- 函数式编程指引
- 概述
- 迭代器
- 生成器表达式和列表推导式
- 生成器
- 内置函数
- itertools 模块
- The functools module
- Small functions and the lambda expression
- Revision History and Acknowledgements
- 引用文献
- 日志 HOWTO
- 日志基础教程
- 进阶日志教程
- 日志级别
- 有用的处理程序
- 记录日志中引发的异常
- 使用任意对象作为消息
- 优化
- 日志操作手册
- 在多个模块中使用日志
- 在多线程中使用日志
- 使用多个日志处理器和多种格式化
- 在多个地方记录日志
- 日志服务器配置示例
- 处理日志处理器的阻塞
- Sending and receiving logging events across a network
- Adding contextual information to your logging output
- Logging to a single file from multiple processes
- Using file rotation
- Use of alternative formatting styles
- Customizing LogRecord
- Subclassing QueueHandler - a ZeroMQ example
- Subclassing QueueListener - a ZeroMQ example
- An example dictionary-based configuration
- Using a rotator and namer to customize log rotation processing
- A more elaborate multiprocessing example
- Inserting a BOM into messages sent to a SysLogHandler
- Implementing structured logging
- Customizing handlers with dictConfig()
- Using particular formatting styles throughout your application
- Configuring filters with dictConfig()
- Customized exception formatting
- Speaking logging messages
- Buffering logging messages and outputting them conditionally
- Formatting times using UTC (GMT) via configuration
- Using a context manager for selective logging
- 正则表达式HOWTO
- 概述
- 简单模式
- 使用正则表达式
- 更多模式能力
- 修改字符串
- 常见问题
- 反馈
- 套接字编程指南
- 套接字
- 创建套接字
- 使用一个套接字
- 断开连接
- 非阻塞的套接字
- 排序指南
- 基本排序
- 关键函数
- Operator 模块函数
- 升序和降序
- 排序稳定性和排序复杂度
- 使用装饰-排序-去装饰的旧方法
- 使用 cmp 参数的旧方法
- 其它
- Unicode 指南
- Unicode 概述
- Python's Unicode Support
- Reading and Writing Unicode Data
- Acknowledgements
- 如何使用urllib包获取网络资源
- 概述
- Fetching URLs
- 处理异常
- info and geturl
- Openers and Handlers
- Basic Authentication
- Proxies
- Sockets and Layers
- 脚注
- Argparse 教程
- 概念
- 基础
- 位置参数介绍
- Introducing Optional arguments
- Combining Positional and Optional arguments
- Getting a little more advanced
- Conclusion
- ipaddress模块介绍
- 创建 Address/Network/Interface 对象
- 审查 Address/Network/Interface 对象
- Network 作为 Address 列表
- 比较
- 将IP地址与其他模块一起使用
- 实例创建失败时获取更多详细信息
- Argument Clinic How-To
- The Goals Of Argument Clinic
- Basic Concepts And Usage
- Converting Your First Function
- Advanced Topics
- 使用 DTrace 和 SystemTap 检测CPython
- Enabling the static markers
- Static DTrace probes
- Static SystemTap markers
- Available static markers
- SystemTap Tapsets
- 示例
- Python 常见问题
- Python常见问题
- 一般信息
- 现实世界中的 Python
- 编程常见问题
- 一般问题
- 核心语言
- 数字和字符串
- 性能
- 序列(元组/列表)
- 对象
- 模块
- 设计和历史常见问题
- 为什么Python使用缩进来分组语句?
- 为什么简单的算术运算得到奇怪的结果?
- 为什么浮点计算不准确?
- 为什么Python字符串是不可变的?
- 为什么必须在方法定义和调用中显式使用“self”?
- 为什么不能在表达式中赋值?
- 为什么Python对某些功能(例如list.index())使用方法来实现,而其他功能(例如len(List))使用函数实现?
- 为什么 join()是一个字符串方法而不是列表或元组方法?
- 异常有多快?
- 为什么Python中没有switch或case语句?
- 难道不能在解释器中模拟线程,而非得依赖特定于操作系统的线程实现吗?
- 为什么lambda表达式不能包含语句?
- 可以将Python编译为机器代码,C或其他语言吗?
- Python如何管理内存?
- 为什么CPython不使用更传统的垃圾回收方案?
- CPython退出时为什么不释放所有内存?
- 为什么有单独的元组和列表数据类型?
- 列表是如何在CPython中实现的?
- 字典是如何在CPython中实现的?
- 为什么字典key必须是不可变的?
- 为什么 list.sort() 没有返回排序列表?
- 如何在Python中指定和实施接口规范?
- 为什么没有goto?
- 为什么原始字符串(r-strings)不能以反斜杠结尾?
- 为什么Python没有属性赋值的“with”语句?
- 为什么 if/while/def/class语句需要冒号?
- 为什么Python在列表和元组的末尾允许使用逗号?
- 代码库和插件 FAQ
- 通用的代码库问题
- 通用任务
- 线程相关
- 输入输出
- 网络 / Internet 编程
- 数据库
- 数学和数字
- 扩展/嵌入常见问题
- 可以使用C语言中创建自己的函数吗?
- 可以使用C++语言中创建自己的函数吗?
- C很难写,有没有其他选择?
- 如何从C执行任意Python语句?
- 如何从C中评估任意Python表达式?
- 如何从Python对象中提取C的值?
- 如何使用Py_BuildValue()创建任意长度的元组?
- 如何从C调用对象的方法?
- 如何捕获PyErr_Print()(或打印到stdout / stderr的任何内容)的输出?
- 如何从C访问用Python编写的模块?
- 如何从Python接口到C ++对象?
- 我使用Setup文件添加了一个模块,为什么make失败了?
- 如何调试扩展?
- 我想在Linux系统上编译一个Python模块,但是缺少一些文件。为什么?
- 如何区分“输入不完整”和“输入无效”?
- 如何找到未定义的g++符号__builtin_new或__pure_virtual?
- 能否创建一个对象类,其中部分方法在C中实现,而其他方法在Python中实现(例如通过继承)?
- Python在Windows上的常见问题
- 我怎样在Windows下运行一个Python程序?
- 我怎么让 Python 脚本可执行?
- 为什么有时候 Python 程序会启动缓慢?
- 我怎样使用Python脚本制作可执行文件?
- *.pyd 文件和DLL文件相同吗?
- 我怎样将Python嵌入一个Windows程序?
- 如何让编辑器不要在我的 Python 源代码中插入 tab ?
- 如何在不阻塞的情况下检查按键?
- 图形用户界面(GUI)常见问题
- 图形界面常见问题
- Python 是否有平台无关的图形界面工具包?
- 有哪些Python的GUI工具是某个平台专用的?
- 有关Tkinter的问题
- “为什么我的电脑上安装了 Python ?”
- 什么是Python?
- 为什么我的电脑上安装了 Python ?
- 我能删除 Python 吗?
- 术语对照表
- 文档说明
- Python 文档贡献者
- 解决 Bug
- 文档错误
- 使用 Python 的错误追踪系统
- 开始为 Python 贡献您的知识
- 版权
- 历史和许可证
- 软件历史
- 访问Python或以其他方式使用Python的条款和条件
- Python 3.7.3 的 PSF 许可协议
- Python 2.0 的 BeOpen.com 许可协议
- Python 1.6.1 的 CNRI 许可协议
- Python 0.9.0 至 1.2 的 CWI 许可协议
- 集成软件的许可和认可
- Mersenne Twister
- 套接字
- Asynchronous socket services
- Cookie management
- Execution tracing
- UUencode and UUdecode functions
- XML Remote Procedure Calls
- test_epoll
- Select kqueue
- SipHash24
- strtod and dtoa
- OpenSSL
- expat
- libffi
- zlib
- cfuhash
- libmpdec