本篇文章是python正则匹配字符手册,用于方便查阅元字符和转义字符相关的细节,不涉及正则表达式如何书写问题。 这部分内容更像是一个手册,用来以后查询使用,想要全部记住有些不容易的。
大多数字母和符号都会简单地匹配自身。例如,正则表达式 test
将会精确地匹配到 test
。但该规则有例外:有些字符是特殊的 元字符(metacharacters),并不匹配自身。
一、元字符
元字符是一种特殊的字符,它并不匹配自身,事实上,它们表示匹配一些非常规的内容,或者通过重复它们或改变它们的含义来影响正则的其他部分。正则表达式的编写几乎就是围绕如何运用元字符来展开的。
这是元字符的完整列表。
. ^ $ * + ? { } [ ] \ | ( )
.
(点号.) 在默认模式下,匹配除换行符以外的任意字符。 如果指定了旗标 DOTALL
,它将匹配包括换行符在内的任意字符。 (?s:.)
将匹配任意字符而无视相关旗标。
^
(插入符) 匹配字符串的开头, 并且在 MULTILINE
模式下也匹配换行后的首个符号。
$
匹配字符串尾或者在字符串尾的换行符的前一个字符,在 MULTILINE
模式下也会匹配换行符之前的文本。 foo
匹配 'foo' 和 'foobar',但正则表达式 foo$
只匹配 'foo'。 更有趣的是,在 'foo1\nfoo2\n'
中搜索 foo.$
,通常匹配 'foo2',但在 MULTILINE
模式下可以匹配到 'foo1';在 'foo\n'
中搜索 $
会找到两个(空的)匹配:一个在换行符之前,一个在字符串的末尾。
*
对它前面的正则式匹配0到任意次重复, 尽量多的匹配字符串。 ab*
会匹配 'a'
,'ab'
,或者 'a'
后面跟随任意个 'b'
。
+
对它前面的正则式匹配1到任意次重复。 ab+
会匹配 'a'
后面跟随1个以上到任意个 'b'
,它不会匹配 'a'
。
?
对它前面的正则式匹配0到1次重复。 ab?
会匹配 'a'
或者 'ab'
。
*?, +?, ??
'*'
, '+'
和 '?'
数量限定符都是 贪婪的;它们会匹配尽可能多的文本。 有时这种行为并不被需要;如果 RE <.*>
针对 '<a> b <c>'
进行匹配,它将匹配整个字符串,而不只是 '<a>'
。 在数量限定符之后添加 ?
将使其以 非贪婪 或 最小 风格来执行匹配;也就是将匹配数量尽可能 少的 字符。 使用 RE <.*?>
将只匹配 '<a>'
。
*+, ++, ?+
类似于 '*'
, '+'
和 '?'
数量限定符,添加了 '+'
的形式也将匹配尽可能多的次数。 但是,不同于真正的贪婪型数量限定符,这些形式在之后的表达式匹配失败时不允许反向追溯。 这些形式被称为 占有型 数量限定符。 例如,a*a
将匹配 'aaaa'
因为 a*
将匹配所有的 4 个 'a'
,但是,当遇到最后一个 'a'
时,表达式将执行反向追溯以便最终 a*
最后变为匹配总计 3 个 'a'
,而第四个 'a'
将由最后一个 'a'
来匹配。 然而,当使用 a*+a
时如果要匹配 'aaaa'
,a*+
将匹配所有的 4 个 'a'
,但是在最后一个 'a'
无法找到更多字符来匹配时,表达式将无法被反向追溯并将因此匹配失败。 x*+
, x++
和 x?+
分别等价于 (?>x*)
, (?>x+)
和 (?>x?)
。Added in version 3.11.
{m}
对其之前的正则式指定匹配 m 个重复;少于 m 的话就会导致匹配失败。比如, a{6}
将匹配6个 'a'
, 但是不能是5个。
{m,n}
对正则式进行 m 到 n 次匹配,在 m 和 n 之间取尽量多。 比如,a{3,5}
将匹配 3 到 5个 'a'
。忽略 m 意为指定下界为0,忽略 n 指定上界为无限次。 比如 a{4,}b
将匹配 'aaaab'
或者1000个 'a'
尾随一个 'b'
,但不能匹配 'aaab'
。逗号不能省略,否则无法辨别修饰符应该忽略哪个边界。
{m,n}?
将导致结果 RE 匹配之前 RE 的 m 至 n 次重复,尝试匹配尽可能 少的 重复次数。 这是之前数量限定符的非贪婪版本。 例如,在 6 个字符的字符串 'aaaaaa' 上,a{3,5} 将匹配 5 个 'a' 字符,而 a{3,5}? 将只匹配 3 个字符。
{m,n}+
将导致结果 RE 匹配之前 RE 的 m 至 n 次重复,尝试匹配尽可能多的重复而 不会 建立任何反向追溯点。 这是上述数量限定符的占有型版本。 例如,在 6 个字符的字符串 'aaaaaa' 上,a{3,5}+aa 将尝试匹配 5 个 'a' 字符,然后,要求再有 2 个 'a',这将需要比可用的更多的字符因而会失败,而 a{3,5}aa 的匹配将使 a{3,5} 先捕获 5 个,然后通过反向追溯再匹配 4 个 'a',然后用模式中最后的 aa 来匹配最后的 2 个 'a'。 x{m,n}+ 就等同于 (?>x{m,n})。
Added in version 3.11.
\
转义特殊字符(允许你匹配 '*'
, '?'
, 或者此类其他),或者表示一个特殊序列;特殊序列之后进行讨论。如果你没有使用原始字符串( r'raw'
)来表达样式,要牢记Python也使用反斜杠作为转义序列;如果转义序列不被Python的分析器识别,反斜杠和字符才能出现在字符串中。如果Python可以识别这个序列,那么反斜杠就应该重复两次。这将导致理解障碍,所以高度推荐,就算是最简单的表达式,也要使用原始字符串。
[]
用于表示一个字符集合。在一个集合中:
-
字符可以单独列出,比如
[amk]
匹配'a'
,'m'
, 或者'k'
。 -
可以表示字符范围,通过用
'-'
将两个字符连起来。比如[a-z]
将匹配任何小写ASCII字符,[0-5][0-9]
将匹配从00
到59
的两位数字,[0-9A-Fa-f]
将匹配任何十六进制数位。 如果-
进行了转义 (比如[a\-z]
)或者它的位置在首位或者末尾(如[-a]
或[a-]
),它就只表示普通字符'-'
。 -
除反斜杠外的特殊字符在集中中会失去其特殊含义。 例如,
[(+*)]
将匹配字符字面值'('
,'+'
,'*'
, 或')'
中的任何一个。 -
反斜杠或者用于转义集合中具有特殊含义的字符如
'-'
,']'
,'^'
及'\\'
本身或者用于提示代表单个字符的特殊序列如\xa0
或\n
或者用于字符类如\w
或\S
(定义见下文)。 请注意\b
是表示单个 "backspace" 字符,而不是如在集合以外那样表示单词边界,还有数字转义符如\1
将总是为八进制形式的转义,而不是分组引用。 不匹配单个字符的特殊转义符如\A
和\Z
是不被允许的。are not allowed. -
不在集合范围内的字符可以通过 取反 来进行匹配。如果集合首字符是
'^'
,所有 不 在集合内的字符将会被匹配,比如[^5]
将匹配所有字符,除了'5'
,[^^]
将匹配所有字符,除了'^'
.^
如果不在集合首位,就没有特殊含义。 -
要在集合内匹配一个
']'
字面值,可以在它前面加上反斜杠,或是将它放到集合的开头。 例如,[()[\]{}]
和[]()[{}]
都可以匹配右方括号,以及左方括号,花括号和圆括号。 -
Unicode Technical Standard #18 里的嵌套集合和集合操作支持可能在未来添加。这将会改变语法,所以为了帮助这个改变,一个
FutureWarning
将会在有多义的情况里被raise
,包含以下几种情况,集合由'['
开始,或者包含下列字符序列'--'
,'&&'
,'~~'
, 和'||'
。为了避免警告,需要将它们用反斜杠转义。
在 3.7 版本发生变更: 如果一个字符串构建的语义在未来会改变的话,一个
FutureWarning
会raise
。
|
A|B
, A 和 B 可以是任意正则表达式,创建一个正则表达式,匹配 A 或者 B. 任意个正则表达式可以用 '|'
连接。它也可以在组合(见下列)内使用。扫描目标字符串时, '|'
分隔开的正则样式从左到右进行匹配。当一个样式完全匹配时,这个分支就被接受。意思就是,一旦 A 匹配成功, B 就不再进行匹配,即便它能产生一个更好的匹配。或者说,'|'
操作符绝不贪婪。 如果要匹配 '|'
字符,使用 \|
, 或者把它包含在字符集里,比如 [|]
.
(...)
(组合),匹配括号内的任意正则表达式,并标识出组合的开始和结尾。匹配完成后,组合的内容可以被获取,并可以在之后用 \number
转义序列进行再次匹配,之后进行详细说明。要匹配字符 '('
或者 ')'
, 用 \(
或 \)
, 或者把它们包含在字符集合里: [(]
, [)]
.
(?…)
这是个扩展标记法 (一个 '?'
跟随 '('
并无含义)。 '?'
后面的第一个字符决定了这个构建采用什么样的语法。这种扩展通常并不创建新的组合; (?P<name>...)
是唯一的例外。 以下是目前支持的扩展。
(?aiLmsux)
一个或多个来自 'a'
, 'i'
, 'L'
, 'm'
, 's'
, 'u'
, 'x'
集合的字母。) 分组将与空字符串相匹配;这些字母将为整个正则表达式设置相应的旗标:
re.A
(仅限 ASCII 匹配)re.I
(忽略大小写)re.L
(依赖于语言区域)re.M
(多行)re.S
(点号匹配所有字符)re.U
(Unicode 匹配)re.X
(详细)
(该旗标在 模块内容 中有介绍。) 这适用于当你希望将该旗标包括为正则表达式的一部分,而不是向 re.compile()
函数传入 flag 参数的情况。 旗标应当在表达式字符串的开头使用。
在 3.11 版本发生变更: 此构造只能在表达式的开头使用。
(?:…)
正则括号的非捕获版本。 匹配在括号内的任何正则表达式,但该分组所匹配的子字符串 不能 在执行匹配后被获取或是之后在模式中被引用。
(?aiLmsux-imsx:…)
(零个或多个来自 'a'
, 'i'
, 'L'
, 'm'
, 's'
, 'u'
, 'x'
集合的字母,后面可以带 '-'
再跟一个或多个来自 'i'
, 'm'
, 's'
, 'x'
集合的字母。) 这些字母将为这部分表达式设置或移除相应的旗标:
re.A
(仅限 ASCII 匹配)re.I
(忽略大小写)re.L
(依赖于语言区域)re.M
(多行)re.S
(点号匹配所有字符)re.U
(Unicode 匹配)re.X
(详细)
(这些旗标在 模块内容 中有介绍。)
字母 'a'
, 'L'
和 'u'
在用作内联旗标时是互斥的,所以它们不能相互组合或者带 '-'
。 相反,当它们中的某一个出现于内联的分组时,它将覆盖外层分组中匹配的模式。 在 Unicode 模式中 (?a:...)
将切换至仅限 ASCII 匹配,而 (?u:...)
将切换至 Unicode 匹配(默认)。 在字节串模式中 (?L:...)
将切换为基于语言区域的匹配,而 (?a:...)
将切换为仅限 ASCII 匹配(默认)。 这种覆盖将只在内联分组范围内生效,而在分组之外将恢复为原始的匹配模式。
Added in version 3.6.
在 3.7 版本发生变更: 符号
'a'
,'L'
和'u'
同样可以用在一个组合内。
(?>...)
尝试匹配 ...
就像它是一个单独的正则表达式,如果匹配成功,则继续匹配在它之后的剩余表达式。 如果之后的表达式匹配失败,则栈只能回溯到 (?>...)
之前 的点,因为一旦退出,这个被称为 原子化分组 的表达式将会丢弃其自身所有的栈点位。 因此,(?>.*).
将永远不会匹配任何东西因为首先 .*
将匹配所有可能的字符,然后,由于没有任何剩余的字符可供匹配,最后的 .
将匹配失败。 由于原子化分组中没有保存任何栈点位,并且在它之前也没有任何栈点位,因此整个表达式将匹配失败。
Added in version 3.11.
(?P<name>…)
与常规的圆括号类似,但分组所匹配到了子字符串可通过符号分组名称 name 来访问。 分组名称必须是有效的 Python 标识符,并且在 bytes
模式中它们只能包含 ASCII 范围内的字节值。 每个分组名称在一个正则表达式中只能定义一次。 一个符号分组同时也是一个编号分组,就像这个分组没有被命名过一样。
命名组合可以在三种上下文中引用。如果样式是 (?P<quote>['"]).*?(?P=quote)
(也就是说,匹配单引号或者双引号括起来的字符串):
引用组合 "quote" 的上下文 | 引用方法 |
---|---|
在正则式自身内 | (?P=quote) (如示)\1 |
处理匹配对象 m | m.group('quote')``m.end('quote') (等) |
传递到 re.sub() 里的 repl 参数中 |
\g<quote>``\g<1>``\1 |
在 3.12 版本发生变更: 在
bytes
模式中,分组 name 只能包含 ASCII 范围内的字节值 (b'\x00'
-b'\x7f'
)。
(?P=name)
反向引用一个命名组合;它匹配前面那个叫 name 的命名组中匹配到的串同样的字串。
(?#…)
注释;里面的内容会被忽略。
(?=…)
当 …
匹配时,匹配成功,但不消耗字符串中的任何字符。这个叫做 前视断言 (lookahead assertion)。比如, Isaac (?=Asimov)
将会匹配 'Isaac '
,仅当其后紧跟 'Asimov'
。
(?!…)
当 …
不匹配时,匹配成功。这个叫 否定型前视断言 (negative lookahead assertion)。例如, Isaac (?!Asimov)
将会匹配 'Isaac '
,仅当它后面 不是 'Asimov'
。
(?<=…)
如果 ...
的匹配内容出现在当前位置的左侧,则匹配。这叫做 肯定型后视断言 (positive lookbehind assertion)。 (?<=abc)def
将会在 'abcdef'
中找到一个匹配,因为后视会回退3个字符并检查内部表达式是否匹配。内部表达式(匹配的内容)必须是固定长度的,意思就是 abc
或 a|b
是允许的,但是 a*
和 a{3,4}
不可以。注意,以肯定型后视断言开头的正则表达式,匹配项一般不会位于搜索字符串的开头。很可能你应该使用 search()
函数,而不是 match()
函数:
>>> import re
>>> m = re.search('(?<=abc)def', 'abcdef')
>>> m.group(0)
'def'
这个例子搜索一个跟随在连字符后的单词:
>>> m = re.search(r'(?<=-)\w+', 'spam-egg')
>>> m.group(0)
'egg'
在 3.5 版本发生变更: 添加定长组合引用的支持。
(?<!…)
如果 ...
的匹配内容没有出现在当前位置的左侧,则匹配。这个叫做 否定型后视断言 (negative lookbehind assertion)。类似于肯定型后视断言,内部表达式(匹配的内容)必须是固定长度的。以否定型后视断言开头的正则表达式,匹配项可能位于搜索字符串的开头。
(?(id/name)yes-pattern|no-pattern)
如果给定的 id 或 name 存在,将会尝试匹配 yes-pattern
,否则就尝试匹配 no-pattern
,no-pattern
可选,也可以被忽略。比如, (<)?(\w+@\w+(?:\.\w+)+)(?(1)>|$)
是一个email样式匹配,将匹配 '<user@host.com>'
或 'user@host.com'
,但不会匹配 '<user@host.com'
,也不会匹配 'user@host.com>'
。
在 3.12 版本发生变更: 分组 id 只能包含 ASCII 数码。 在
bytes
模式中,分组 name 只能包含 ASCII 范围内的字节值 (b'\x00'
-b'\x7f'
)。
由 '\'
和一个字符组成的特殊序列在以下列出。 如果普通字符不是ASCII数位或者ASCII字母,那么正则样式将匹配第二个字符。比如,\$
匹配字符 '$'
.
二、转义字符
转义字符是通过转义符号\加上字母或者数字的特殊组合形式用以代表特定字符序列的组合字符。
\number
匹配数字代表的组合。每个括号是一个组合,组合从1开始编号。比如 (.+) \1
匹配 'the the'
或者 '55 55'
, 但不会匹配 'thethe'
(注意组合后面的空格)。这个特殊序列只能用于匹配前面99个组合。如果 number 的第一个数位是0, 或者 number 是三个八进制数,它将不会被看作是一个组合,而是八进制的数字值。在 '['
和 ']'
字符集合内,任何数字转义都被看作是字符。
\A
只匹配字符串开始。
\b
匹配空字符串,但只在单词开始或结尾的位置。 一个单词被定义为一个单词字符的序列。 注意在通常情况下,\b
被定义为 \w
和 \W
字符之间的边界(反之亦然),或是 \w
和字符串开始或结尾之间的边界。 这意味着 r'\bat\b'
将匹配 'at'
, 'at.'
, '(at)'
和 'as at ay'
但不匹配 'attempt'
或 'atlas'
。
Unicode (str) 模式中默认的单词类字符是 Unicode 字母数字和下划线,但这可以通过使用 ASCII
旗标来改变。 如果使用了 LOCALE
旗标则单词边界将根据当前语言区域来确定。
备注:在一个字符范围内,
\b
代表退格符,以便与 Python 的字符串字面值保持兼容。
\B
匹配空字符串,但仅限于它 不在 单词的开头或结尾的情况。 这意味着 r'at\B'
将匹配 'athens'
, 'atom'
, 'attorney'
,但不匹配 'at'
, 'at.'
或 'at!'
。 \B
与 \b
正相反,这样 Unicode (str) 模式中的单词类字符是 Unicode 字母数字或下划线,但这可以通过使用 ASCII
旗标来改变。 如果使用了 LOCALE
旗标则单词边界将根据当前语言区域来确定。
备注:请注意
\B
不会匹配空字符串,这与其他编程语言如 Perl 的 RE 实现不同。 此行为是出于兼容性考虑而保留的。
\d
-
对于 Unicode (str) 样式:
匹配任意 Unicode 十进制数码(也就是说,任何属于 Unicode 字符类别 [Nd] 的字符)。 这包括
[0-9]
,还包括许多其他的数码类字符。如果使用了ASCII
旗标则匹配[0-9]
-
对于8位(bytes)样式:
匹配 ASCII 字符集内的任意十进制数码;这等价于
[0-9]
。
\D
匹配不属于十进制数码的任意字符。 这与 \d
正相反。
如果使用了 ASCII
旗标则匹配 [^0-9]
\s
-
对于 Unicode (str) 样式:
匹配 Unicode 空白字符(如
str.isspace()
所定义的)。 这包括[ \t\n\r\f\v]
,还包括许多其他字符,例如许多语言中由排版规则约定的非中断空白字符。如果使用了ASCII
旗标则匹配[ \t\n\r\f\v]
。 -
对于8位(bytes)样式:
匹配ASCII中的空白字符,就是
[ \t\n\r\f\v]
。
\S
匹配不属于空白字符的任意字符。 这与 \s
正相反。
如果使用了 ASCII
旗标则匹配 [^ \t\n\r\f\v]
\w
-
对于 Unicode (str) 样式:
匹配 Unicode 单词类字符;这包括所有 Unicode 字母数字类字符 (由
str.isalnum()
定义),以及下划线 (_
)。如果使用了ASCII
旗标则匹配[a-zA-Z0-9_]
。 -
对于8位(bytes)样式:
匹配在 ASCII 字符集中被视为字母数字的字符;这等价于
[a-zA-Z0-9_]
。 如果使用了LOCALE
旗标,则匹配在当前语言区域中被视为字母数字的字符以及下划线。
\W
匹配不属于单词类字符的任意字符。 这与 \w
正相反。 在默认情况下,将匹配除下划线 (_
) 以外的 str.isalnum()
返回 False
的字符。
如果使用了 ASCII
旗标则匹配 [^a-zA-Z0-9_]
。
如果使用了 LOCALE
旗标,则匹配在当前语言区域中不属于字母数字且不为下划线的字符。
\Z
只匹配字符串尾。
Python 字符串字面值支持的大多数 转义序列 也被正则表达式解析器所接受:
\a \b \f \n
\N \r \t \u
\U \v \x \\
(注意 \b
被用于表示词语的边界,它只在字符集合内表示退格,比如 [\b]
。)
'\u'
, '\U'
和 '\N'
转义序列仅在 Unicode (str) 模式中可被识别。 在字节串模式中它们会导致错误。 未知的 ASCII 字母转义符被保留在未来使用并会被视为错误。
八进制转义包含为一个有限形式。如果首位数字是 0, 或者有三个八进制数位,那么就认为它是八进制转义。其他的情况,就看作是组引用。对于字符串文本,八进制转义最多有三个数位长。
在 3.3 版本发生变更: 增加了
'\u'
和'\U'
转义序列。
在 3.6 版本发生变更: 由
'\'
和一个ASCII字符组成的未知转义会被看成错误。
在 3.8 版本发生变更: 增加了
'\N{*name*}'
转义序列。 与在字符串字面值中一样,它扩展了指定的 Unicode 字符 (例如'\N{EM DASH}'
)。
参考文档:《re
--- 正则表达式操作》
注意:本文归作者所有,未经作者允许,不得转载