Re正则表达式
- Python Re模块
- 正则表达式HOWTO
正则表达式语法
正则表达式(或 RE)指定了一组与之匹配的字符串;模块内的函数可以检查某个字符串是否与给定的正则表达式匹配(或者正则表达式是否匹配到字符串,这两种说法含义相同)。
正则表达式可以拼接;如果 A 和 B 都是正则表达式,则 AB 也是正则表达式。通常,如果字符串 p 匹配 A,并且另一个字符串 q 匹配 B,那么 pq 可以匹配 AB。除非 A 或者 B 包含低优先级操作,A 和 B 存在边界条件;或者命名组引用。所以,复杂表达式可以很容易的从这里描述的简单源语表达式构建。
正则表达式可以包含普通或者特殊字符。绝大部分普通字符,比如 'A'
, 'a'
, 或者 '0'
,都是最简单的正则表达式。它们就匹配自身。你可以拼接普通字符,所以 last
匹配字符串 'last'
. (在这一节的其他部分,我们将用 this special style
这种方式表示正则表达式,通常不带引号,要匹配的字符串用 'in single quotes'
,单引号形式。)
有些字符,比如 '|'
或者 '('
,属于特殊字符。 特殊字符既可以表示它的普通含义, 也可以影响它旁边的正则表达式的解释。
重复修饰符 (*
, +
, ?
, {m,n}
, 等) 不能直接嵌套。这样避免了非贪婪后缀 ?
修饰符,和其他实现中的修饰符产生的多义性。要应用一个内层重复嵌套,可以使用括号。 比如,表达式 (?:a{6})*
匹配6个 'a'
字符重复任意次数。
特殊字符
.
(点) 在默认模式,匹配除了换行的任意字符。如果指定了标签 [DOTALL](<https://docs.python.org/zh-cn/3/library/re.html#re.DOTALL>)
,它将匹配包括换行符的任意字符。
^
(插入符号) 匹配字符串的开头, 并且在 [MULTILINE](<https://docs.python.org/zh-cn/3/library/re.html#re.MULTILINE>)
模式也匹配换行后的首个符号。
$
匹配字符串尾或者在字符串尾的换行符的前一个字符,在 [MULTILINE](<https://docs.python.org/zh-cn/3/library/re.html#re.MULTILINE>)
模式下也会匹配换行符之前的文本。 foo
匹配 ‘foo’ 和 ‘foobar’,但正则表达式 foo$
只匹配 ‘foo’。 更有趣的是,在 'foo1\\nfoo2\\n'
中搜索 foo.$
,通常匹配 ‘foo2’,但在 [MULTILINE](<https://docs.python.org/zh-cn/3/library/re.html#re.MULTILINE>)
模式下可以匹配到 ‘foo1’;在 'foo\\n'
中搜索 $
会找到两个(空的)匹配:一个在换行符之前,一个在字符串的末尾。
*
对它前面的正则式匹配0到任意次重复, 尽量多的匹配字符串。 ab*
会匹配 'a'
,'ab'
,或者 'a'
后面跟随任意个 'b'
。
+
对它前面的正则式匹配1到任意次重复。 ab+
会匹配 'a'
后面跟随1个以上到任意个 'b'
,它不会匹配 'a'
。
?
对它前面的正则式匹配0到1次重复。 ab?
会匹配 'a'
或者 'ab'
。
***?
, +?
, ??
**
'*'
, '+'
,和 '?'
修饰符都是 贪婪的;它们在字符串进行尽可能多的匹配。有时候并不需要这种行为。如果正则式 <.*>
希望找到 '<a> b <c>'
,它将会匹配整个字符串,而不仅是 '<a>'
。在修饰符之后添加 ?
将使样式以 非贪婪方式进行匹配; 尽量少的字符将会被匹配。 使用正则式 <.*?>
将会仅仅匹配 '<a>'
。
{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}?
前一个修饰符的非贪婪模式,只匹配尽量少的字符次数。比如,对于 'aaaaaa'
, a{3,5}
匹配 5个 'a'
,而 a{3,5}?
只匹配3个 'a'
。
\\
转义特殊字符(允许你匹配 '*'
, '?'
, 或者此类其他),或者表示一个特殊序列;特殊序列之后进行讨论。 如果你没有使用原始字符串( 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-]
),它就只表示普通字符'-'
。 - 特殊字符在集合中,失去它的特殊含义。比如
[(+*)]
只会匹配这几个文法字符'('
,'+'
,'*'
, or')'
。 - 字符类如
\\w
或者\\S
(如下定义) 在集合内可以接受,它们可以匹配的字符由[ASCII](<https://docs.python.org/zh-cn/3/library/re.html#re.ASCII>)
或者[LOCALE](<https://docs.python.org/zh-cn/3/library/re.html#re.LOCALE>)
模式决定。 - 不在集合范围内的字符可以通过 取反 来进行匹配。如果集合首字符是
'^'
,所有 不 在集合内的字符将会被匹配,比如[^5]
将匹配所有字符,除了'5'
,[^^]
将匹配所有字符,除了'^'
.^
如果不在集合首位,就没有特殊含义。 - 在集合内要匹配一个字符
']'
,有两种方法,要么就在它之前加上反斜杠,要么就把它放到集合首位。比如,[()[\\]{}]
和[]()[{}]
都可以匹配括号。 - Unicode Technical Standard #18 里的嵌套集合和集合操作支持可能在未来添加。这将会改变语法,所以为了帮助这个改变,一个
[FutureWarning](<https://docs.python.org/zh-cn/3/library/exceptions.html#FutureWarning>)
将会在有多义的情况里被raise
,包含以下几种情况,集合由'['
开始,或者包含下列字符序列'--'
,'&&'
,'~~'
, 和'||'
。为了避免警告,需要将它们用反斜杠转义。
在 3.7 版更改: 如果一个字符串构建的语义在未来会改变的话,个 [FutureWarning](<https://docs.python.org/zh-cn/3/library/exceptions.html#FutureWarning>)
会 raise
。
|
A|B
, A 和 B 可以是任意正则表达式,创建一个正则表达式,匹配 A 或者 B. 任意个正则表达式可以用 '|'
连接。它也可以在组合(见下列)内使用。扫描目标字符串时, '|'
分隔开的正则样式从左到右进行匹配。当一个样式完全匹配时,这个分支就被接受。意思就是,一旦 A 匹配成功, B 就不再进行匹配,即便它能产生一个更好的匹配。或者说,'|'
操作符绝不贪婪。 如果要匹配 '|'
字符,使用 \\|
, 或者把它包含在字符集里,比如 [|]
.
(...)
(组合),匹配括号内的任意正则表达式,并标识出组合的开始和结尾。匹配完成后,组合的内容可以被获取,并可以在之后用 \\number
转义序列进行再次匹配,之后进行详细说明。要匹配字符 '('
或者 ')'
, 用 \\(
或 \\)
, 或者把它们包含在字符集合里: [(]
, [)]
.
(?…)
这是个扩展标记法 (一个 '?'
跟随 '('
并无含义)。 '?'
后面的第一个字符决定了这个构建采用什么样的语法。这种扩展通常并不创建新的组合; (?P<name>...)
是唯一的例外。 以下是目前支持的扩展。
(?aiLmsux)
( 'a'
, 'i'
, 'L'
, 'm'
, 's'
, 'u'
, 'x'
中的一个或多个) 这个组合匹配一个空字符串;这些字符对正则表达式设置以下标记 [re.A](<https://docs.python.org/zh-cn/3/library/re.html#re.A>)
(只匹配ASCII字符), [re.I](<https://docs.python.org/zh-cn/3/library/re.html#re.I>)
(忽略大小写), [re.L](<https://docs.python.org/zh-cn/3/library/re.html#re.L>)
(语言依赖), [re.M](<https://docs.python.org/zh-cn/3/library/re.html#re.M>)
(多行模式), [re.S](<https://docs.python.org/zh-cn/3/library/re.html#re.S>)
(点dot匹配全部字符), re.U
(Unicode匹配), and [re.X](<https://docs.python.org/zh-cn/3/library/re.html#re.X>)
(冗长模式)。 (这些标记在 模块内容 中描述) 如果你想将这些标记包含在正则表达式中,这个方法就很有用,免去了在 [re.compile()](<https://docs.python.org/zh-cn/3/library/re.html#re.compile>)
中传递 flag 参数。标记应该在表达式字符串首位表示。
(?:…)
正则括号的非捕获版本。 匹配在括号内的任何正则表达式,但该分组所匹配的子字符串 *不能* 在执行匹配后被获取或是之后在模式中被引用。
(?aiLmsux-imsx:…)
('a'
, 'i'
, 'L'
, 'm'
, 's'
, 'u'
, 'x'
中的0或者多个, 之后可选跟随 '-'
在后面跟随 'i'
, 'm'
, 's'
, 'x'
中的一到多个 .) 这些字符为表达式的其中一部分 设置 或者 去除 相应标记 [re.A](<https://docs.python.org/zh-cn/3/library/re.html#re.A>)
(只匹配ASCII), [re.I](<https://docs.python.org/zh-cn/3/library/re.html#re.I>)
(忽略大小写), [re.L](<https://docs.python.org/zh-cn/3/library/re.html#re.L>)
(语言依赖), [re.M](<https://docs.python.org/zh-cn/3/library/re.html#re.M>)
(多行), [re.S](<https://docs.python.org/zh-cn/3/library/re.html#re.S>)
(点匹配所有字符), re.U
(Unicode匹配), and [re.X](<https://docs.python.org/zh-cn/3/library/re.html#re.X>)
(冗长模式)。(标记描述在 模块内容 .) 'a'
, 'L'
and 'u'
作为内联标记是相互排斥的, 所以它们不能结合在一起,或者跟随 '-'
。 当他们中的某个出现在内联组中,它就覆盖了括号组内的匹配模式。在Unicode样式中, (?a:...)
切换为 只匹配ASCII, (?u:...)
切换为Unicode匹配 (默认). 在byte样式中 (?L:...)
切换为语言依赖模式, (?a:...)
切换为 只匹配ASCII (默认)。这种方式只覆盖组合内匹配,括号外的匹配模式不受影响。 3.6 新版功能. 在 3.7 版更改: 符号 'a'
, 'L'
和 'u'
同样可以用在一个组合内。
(?P<name>…)
(命名组合)类似正则组合,但是匹配到的子串组在外部是通过定义的 name 来获取的。组合名必须是有效的Python标识符,并且每个组合名只能用一个正则表达式定义,只能定义一次。一个符号组合同样是一个数字组合,就像这个组合没有被命名一样。 命名组合可以在三种上下文中引用。如果样式是 (?P<quote>['"]).*?(?P=quote)
(也就是说,匹配单引号或者双引号括起来的字符串):
(?P=name)
反向引用一个命名组合;它匹配前面那个叫 name 的命名组中匹配到的串同样的字串。
(?#…)
注释;里面的内容会被忽略。
(?=…)
匹配 …
的内容,但是并不消费样式的内容。这个叫做 lookahead assertion。比如, Isaac (?=Asimov)
匹配 'Isaac '
只有在后面是 'Asimov'
的时候。
(?!…)
匹配 …
不符合的情况。这个叫 negative lookahead assertion (前视取反)。比如说, Isaac (?!Asimov)
只有后面 *不* 是 'Asimov'
的时候才匹配 'Isaac '
。
(?<=…)
匹配字符串的当前位置,它的前面匹配 ...
的内容到当前位置。这叫 positive lookbehind assertion (正向后视断定)。 (?<=abc)def
会在 'abcdef'
中找到一个匹配,因为后视会往后看3个字符并检查是否包含匹配的样式。包含的匹配样式必须是定长的,意思就是 abc
或 a|b
是允许的,但是 a*
和 a{3,4}
不可以。注意以 positive lookbehind assertions 开始的样式,如 (?<=abc)def
,并不是从 a 开始搜索,而是从 d 往回看的。你可能更加愿意使用 [search()](<https://docs.python.org/zh-cn/3/library/re.html#re.search>)
函数,而不是 [match()](<https://docs.python.org/zh-cn/3/library/re.html#re.match>)
函数:
import re
m = re.search('(?<=abc)def', 'abcdef')
m.group(0)
'def'
m = re.search(r'(?<=-)\\w+', 'spam-egg')
m.group(0)
'egg'
(?<!…)
匹配当前位置之前不是 ...
的样式。这个叫 negative lookbehind assertion (后视断定取非)。类似正向后视断定,包含的样式匹配必须是定长的。由 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>'
。
由 '\\'
和一个字符组成的特殊序列在以下列出。 如果普通字符不是ASCII数位或者ASCII字母,那么正则样式将匹配第二个字符。比如,\\$
匹配字符 '$'
\\number
匹配数字代表的组合。每个括号是一个组合,组合从1开始编号。比如 (.+) \\1
匹配 'the the'
或者 '55 55'
, 但不会匹配 'thethe'
(注意组合后面的空格)。这个特殊序列只能用于匹配前面99个组合。如果 number 的第一个数位是0, 或者 number 是三个八进制数,它将不会被看作是一个组合,而是八进制的数字值。在 '['
和 ']'
字符集合内,任何数字转义都被看作是字符。
\\A
只匹配字符串开始。
\\b
匹配空字符串,但只在单词开始或结尾的位置。一个单词被定义为一个单词字符的序列。注意,通常 \\b
定义为 \\w
和 \\W
字符之间,或者 \\w
和字符串开始/结尾的边界, 意思就是 r'\\bfoo\\b'
匹配 'foo'
, 'foo.'
, '(foo)'
, 'bar foo baz'
但不匹配 'foobar'
或者 'foo3'
。 默认情况下,Unicode字母和数字是在Unicode样式中使用的,但是可以用 [ASCII](<https://docs.python.org/zh-cn/3/library/re.html#re.ASCII>)
标记来更改。如果 [LOCALE](<https://docs.python.org/zh-cn/3/library/re.html#re.LOCALE>)
标记被设置的话,词的边界是由当前语言区域设置决定的,\\b
表示退格字符,以便与Python字符串文本兼容。
\\B
匹配空字符串,但 *不* 能在词的开头或者结尾。意思就是 r'py\\B'
匹配 'python'
, 'py3'
, 'py2'
, 但不匹配 'py'
, 'py.'
, 或者 'py!'
. \\B
是 \\b
的取非,所以Unicode样式的词语是由Unicode字母,数字或下划线构成的,虽然可以用 [ASCII](<https://docs.python.org/zh-cn/3/library/re.html#re.ASCII>)
标志来改变。如果使用了 [LOCALE](<https://docs.python.org/zh-cn/3/library/re.html#re.LOCALE>)
标志,则词的边界由当前语言区域设置。
\\d
对于 Unicode (str) 样式:匹配任何Unicode十进制数(就是在Unicode字符目录[Nd]里的字符)。这包括了 [0-9]
,和很多其他的数字字符。如果设置了 [ASCII](<https://docs.python.org/zh-cn/3/library/re.html#re.ASCII>)
标志,就只匹配 [0-9]
。对于8位(bytes)样式:匹配任何十进制数,就是 [0-9]
。
\\D
匹配任何非十进制数字的字符。就是 \\d
取非。 如果设置了 [ASCII](<https://docs.python.org/zh-cn/3/library/re.html#re.ASCII>)
标志,就相当于 [^0-9]
。
\\s
对于 Unicode (str) 样式:匹配任何Unicode空白字符(包括 [ \\t\\n\\r\\f\\v]
,还有很多其他字符,比如不同语言排版规则约定的不换行空格)。如果 [ASCII](<https://docs.python.org/zh-cn/3/library/re.html#re.ASCII>)
被设置,就只匹配 [ \\t\\n\\r\\f\\v]
。对于8位(bytes)样式:匹配ASCII中的空白字符,就是 [ \\t\\n\\r\\f\\v]
。
\\S
匹配任何非空白字符。就是 \\s
取非。如果设置了 [ASCII](<https://docs.python.org/zh-cn/3/library/re.html#re.ASCII>)
标志,就相当于 [^ \\t\\n\\r\\f\\v]
。
\\w
对于 Unicode (str) 样式:匹配Unicode词语的字符,包含了可以构成词语的绝大部分字符,也包括数字和下划线。如果设置了 [ASCII](<https://docs.python.org/zh-cn/3/library/re.html#re.ASCII>)
标志,就只匹配 [a-zA-Z0-9_]
。对于8位(bytes)样式:匹配ASCII字符中的数字和字母和下划线,就是 [a-zA-Z0-9_]
。如果设置了 [LOCALE](<https://docs.python.org/zh-cn/3/library/re.html#re.LOCALE>)
标记,就匹配当前语言区域的数字和字母和下划线。
\\W
匹配非单词字符的字符。这与 \\w
正相反。如果使用了 [ASCII](<https://docs.python.org/zh-cn/3/library/re.html#re.ASCII>)
旗标,这就等价于 [^a-zA-Z0-9_]
。如果使用了 [LOCALE](<https://docs.python.org/zh-cn/3/library/re.html#re.LOCALE>)
旗标,则会匹配当前区域中既非字母数字也非下划线的字符。
\\Z
只匹配字符串尾。
绝大部分Python的标准转义字符也被正则表达式分析器支持。:
\\a \\b \\f \\n
\\N \\r \\t \\u
\\U \\v \\x \\\\
(注意 \\b
被用于表示词语的边界,它只在字符集合内表示退格,比如 [\\b]
。)
'\\u'
, '\\U'
和 '\\N'
转义序列只在 Unicode 模式中可被识别。 在 bytes 模式中它们会导致错误。 未知的 ASCII 字母转义序列保留在未来使用,会被当作错误来处理。
八进制转义包含为一个有限形式。如果首位数字是 0, 或者有三个八进制数位,那么就认为它是八进制转义。其他的情况,就看作是组引用。对于字符串文本,八进制转义最多有三个数位长。
模块内容
re.compile
(*pattern*, *flags=0*)
将正则表达式的样式编译为一个 正则表达式对象 (正则对象),可以用于匹配,通过这个对象的方法 [match()](<https://docs.python.org/zh-cn/3/library/re.html#re.Pattern.match>)
, [search()](<https://docs.python.org/zh-cn/3/library/re.html#re.Pattern.search>)
以及其他如下描述。 这个表达式的行为可以通过指定 标记 的值来改变。值可以是以下任意变量,可以通过位的OR操作来结合( |
操作符)。
prog = re.compile(pattern)
result = prog.match(string)
等价于
result = re.match(pattern, string)
re.search
(*pattern*, *string*, *flags=0*)
扫描整个 字符串 找到匹配样式的第一个位置,并返回一个相应的 匹配对象。如果没有匹配,就返回一个 None
; 注意这和找到一个零长度匹配是不同的。
re.match
(*pattern*, *string*, *flags=0*)
如果 string 开始的0或者多个字符匹配到了正则表达式样式,就返回一个相应的 匹配对象 。 如果没有匹配,就返回 None
;注意它跟零长度匹配是不同的。 注意即便是 [MULTILINE](<https://docs.python.org/zh-cn/3/library/re.html#re.MULTILINE>)
多行模式, [re.match()](<https://docs.python.org/zh-cn/3/library/re.html#re.match>)
也只匹配字符串的开始位置,而不匹配每行开始。 如果你想定位 string 的任何位置,使用 [search()](<https://docs.python.org/zh-cn/3/library/re.html#re.search>)
来替代(也可参考 search() vs. match() )
re.fullmatch
(*pattern*, *string*, *flags=0*)
如果整个 string 匹配到正则表达式样式,就返回一个相应的 匹配对象 。 否则就返回一个 None
;注意这跟零长度匹配是不同的。 3.4 新版功能.
re.split
(*pattern*, *string*, *maxsplit=0*, *flags=0*)
用 pattern 分开 string 。 如果在 pattern 中捕获到括号,那么所有的组里的文字也会包含在列表里。如果 maxsplit 非零, 最多进行 maxsplit 次分隔, 剩下的字符全部返回到列表的最后一个元素。
>>> 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.']
>>> re.split('[a-f]+', '0a3B9', flags=re.IGNORECASE)
['0', '3', '9']
如果分隔符里有捕获组合,并且匹配到字符串的开始,那么结果将会以一个空字符串开始。对于结尾也是一样
>>> re.split(r'(\\W+)', '...words, words...')
['', '...', 'words', ', ', 'words', '...', '']
这样的话,分隔组将会出现在结果列表中同样的位置。
样式的空匹配仅在与前一个空匹配不相邻时才会拆分字符串。
re.split(r'\\b', 'Words, words, words.')
['', 'Words', ', ', 'words', ', ', 'words', '.']
re.split(r'\\W*', '...words...')
['', '', 'w', 'o', 'r', 'd', 's', '', '']
re.split(r'(\\W*)', '...words...')
['', '...', '', '', 'w', '', 'o', '', 'r', '', 'd', '', 's', '...', '', '', '']
re.findall
(*pattern*, *string*, *flags=0*)
返回字符串中模式的所有非重叠匹配项,作为字符串或元组列表。从左到右扫描字符串,并按找到的顺序返回匹配项。结果中包含空匹配项。结果取决于模式中捕获组的数量。如果没有组,则返回与整个模式匹配的字符串列表。如果只有一个组,则返回与该组匹配的字符串列表。如果存在多个组,则返回与这些组匹配的字符串元组列表。非捕获组不会影响结果的形式。
re.finditer
(*pattern*, *string*, *flags=0*)
pattern 在 string 里所有的非重复匹配,返回为一个迭代器 iterator 保存了 匹配对象 。 string 从左到右扫描,匹配按顺序排列。空匹配也包含在结果里。 在 3.7 版更改: 非空匹配现在可以在前一个空匹配之后出现了。
re.sub
(*pattern*, *repl*, *string*, *count=0*, *flags=0*)
返回通过使用 *repl* 替换在 *string* 最左边非重叠出现的 *pattern* 而获得的字符串。 如果样式没有找到,则不加改变地返回 string*。 *repl 可以是字符串或函数;如为字符串,则其中任何反斜杠转义序列都会被处理。 也就是说,\\n
会被转换为一个换行符,\\r
会被转换为一个回车符,依此类推。 未知的 ASCII 字符转义序列保留在未来使用,会被当作错误来处理。 其他未知转义序列例如 \\&
会保持原样。 向后引用像是 \\6
会用样式中第 6 组所匹配到的子字符串来替换。 例如:
>>> re.sub(r'def\\s+([a-zA-Z_][a-zA-Z_0-9]*)\\s*\\(\\s*\\):',
... r'static PyObject*\\npy_\\1(void)\\n{',
... 'def myfunc():')
'static PyObject*\\npy_myfunc(void)\\n{'
如果 repl是一个函数,那它会对每个非重复的 pattern的情况调用。这个函数只能有一个 匹配对象参数,并返回一个替换后的字符串。比如
def dashrepl(matchobj):
... if matchobj.group(0) == '-': return ' '
... else: return '-'
>>> re.sub('-{1,2}', dashrepl, 'pro----gram-files')
'pro--gram files'
>>> re.sub(r'\\sAND\\s', ' & ', 'Baked Beans And Spam', flags=re.IGNORECASE)
'Baked Beans & Spam'
样式可以是一个字符串或者一个 样式对象 。
可选参数 count 是要替换的最大次数;count 必须是非负整数。如果省略这个参数或设为 0,所有的匹配都会被替换。 样式的空匹配仅在与前一个空匹配不相邻时才会被替换,所以 sub('x*', '-', 'abxd')
返回 '-a-b--d-'
。
在字符串类型的 repl 参数里,如上所述的转义和向后引用中,\\g<name>
会使用命名组合 name
,(在 (?P<name>…)
语法中定义) \\g<number>
会使用数字组;\\g<2>
就是 \\2
,但它避免了二义性,如 \\g<2>0
。 \\20
就会被解释为组20,而不是组2后面跟随一个字符 '0'
。向后引用 \\g<0>
把 pattern 作为一整个组进行引用。
re.subn
(*pattern*, *repl*, *string*, *count=0*, *flags=0*)
行为与 [sub()](<https://docs.python.org/zh-cn/3/library/re.html#re.sub>)
相同,但是返回一个元组 (字符串, 替换次数)
.
re.escape
(*pattern*)
转义 pattern 中的特殊字符。如果你想对任意可能包含正则表达式元字符的文本字符串进行匹配,它就是有用的。比如
>>> print(re.escape('<https://www.python.org>'))
<https://www>\\.python\\.org
>>> legal_chars = string.ascii_lowercase + string.digits + "!#$%&'*+-.^_`|~:"
>>> print('[%s]+' % re.escape(legal_chars))
[abcdefghijklmnopqrstuvwxyz0123456789!\\#\\$%\\&'\\*\\+\\-\\.\\^_`\\|\\~:]+
>>> operators = ['+', '-', '*', '/', '**']
>>> print('|'.join(map(re.escape, sorted(operators, reverse=True))))
/|\\-|\\+|\\*\\*|\\*
这个函数不能被用于 [sub()](<https://docs.python.org/zh-cn/3/library/re.html#re.sub>)
和 [subn()](<https://docs.python.org/zh-cn/3/library/re.html#re.subn>)
的替换字符串,只有反斜杠应该被转义。 例如:
>>> digits_re = r'\\d+'
>>> sample = '/usr/sbin/sendmail - 0 errors, 12 warnings'
>>> print(re.sub(digits_re, digits_re.replace('\\\\', r'\\\\'), sample))
/usr/sbin/sendmail - \\d+ errors, \\d+ warnings
re.purge
()
清除正则表达式的缓存。
匹配对象
匹配对象总是有一个布尔值 True
。如果没有匹配的话 [match()](<https://docs.python.org/zh-cn/3/library/re.html#re.Pattern.match>)
和 [search()](<https://docs.python.org/zh-cn/3/library/re.html#re.Pattern.search>)
返回 None
所以你可以简单的用 if
语句来判断是否匹配
match = re.search(pattern, string)
if match:
process(match)
Match.expand
(*template*)
对 template 进行反斜杠转义替换并且返回,就像 [sub()](<https://docs.python.org/zh-cn/3/library/re.html#re.Pattern.sub>)
方法中一样。转义如同 \\n
被转换成合适的字符,数字引用(\\1
, \\2
)和命名组合(\\g<1>
, \\g<name>
) 替换为相应组合的内容。
Match.group
([*group1*, *…*])
返回一个或者多个匹配的子组。如果只有一个参数,结果就是一个字符串,如果有多个参数,结果就是一个元组(每个参数对应一个项),如果没有参数,组1默认到0(整个匹配都被返回)。 如果一个组N 参数值为 0,相应的返回值就是整个匹配字符串;如果它是一个范围 [1..99],结果就是相应的括号组字符串。如果一个组号是负数,或者大于样式中定义的组数,就引发一个 [IndexError](<https://docs.python.org/zh-cn/3/library/exceptions.html#IndexError>)
异常。如果一个组包含在样式的一部分,并被匹配多次,就返回最后一个匹配。
>>> m = re.match(r"(\\w+) (\\w+)", "Isaac Newton, physicist")
>>> m.group(0) # The entire match
'Isaac Newton'
>>> m.group(1) # The first parenthesized subgroup.
'Isaac'
>>> m.group(2) # The second parenthesized subgroup.
'Newton'
>>> m.group(1, 2) # Multiple arguments give us a tuple.
('Isaac', 'Newton')
如果正则表达式使用了 (?P<name>...)
语法, groupN 参数就也可能是命名组合的名字。如果一个字符串参数在样式中未定义为组合名,就引发一个 [IndexError](<https://docs.python.org/zh-cn/3/library/exceptions.html#IndexError>)
异常。
一个相对复杂的例子
>>> m = re.match(r"(?P<first_name>\\w+) (?P<last_name>\\w+)", "Malcolm Reynolds")
>>> m.group('first_name')
'Malcolm'
>>> m.group('last_name')
'Reynolds'
Match.__getitem__
(*g*)
这个等价于 m.group(g)
。这允许更方便的引用一个匹配
>>> m = re.match(r"(\\w+) (\\w+)", "Isaac Newton, physicist")
>>> m[0] # The entire match
'Isaac Newton'
>>> m[1] # The first parenthesized subgroup.
'Isaac'
>>> m[2] # The second parenthesized subgroup.
'Newton'
Match.groups
(*default=None*)
返回一个元组,包含所有匹配的子组,在样式中出现的从1到任意多的组合。 default 参数用于不参与匹配的情况,默认为 None
。
Match.groupdict
(*default=None*)
返回一个字典,包含了所有的 *命名* 子组。key就是组名。 default 参数用于不参与匹配的组合;默认为 None
。 例如
>>> m = re.match(r"(?P<first_name>\\w+) (?P<last_name>\\w+)", "Malcolm Reynolds")
>>> m.groupdict()
{'first_name': 'Malcolm', 'last_name': 'Reynolds'}
Match.start
([*group*])
Match.end
([*group*])
返回 group 匹配到的字串的开始和结束标号。group 默认为0(意思是整个匹配的子串)。如果 group 存在,但未产生匹配,就返回 -1
。对于一个匹配对象 m, 和一个未参与匹配的组 g ,组 g (等价于 m.group(g)
)产生的匹配是
m.string[m.start(g):m.end(g)]
Match.span
([*group*])
对于一个匹配 m , 返回一个二元组 (m.start(group), m.end(group))
。 注意如果 group\ 没有在这个匹配中,就返回 (-1, -1)
。group\ 默认为0,就是整个匹配。