正则表达式语法 —— Python

正则表达式是一个特殊的字符序列,能方便地检查一个字符串是否与某种模式匹配。

  • 正则表达式可以拼接。

  • 正则表达式可以包含普通或者特殊字符。

    • 绝大部分普通字符,是最简单的正则表达式。它们就匹配自身。

    • 特殊字符既可以表示它的普通含义, 也可以影响它旁边的正则表达式的解释。

    • 重复修饰符(*+?{m,n}, 等)不能直接嵌套。避免了非贪婪后缀 ? 修饰符,和其他实现中的修饰符产生的多义性。要应用一个内层重复嵌套,可以使用括号。


特殊字符

序列 说明
. (点)在默认模式,匹配除了换行的任意字符。
如果指定了标签 DOTALL,它将匹配包括换行符的任意字符。
\ 转义特殊字符(允许你匹配 '*''?',或者其他正则表达式中使用的特殊字符),或者表示一个特殊序列。
[…] 用于表示一个字符集合。
字符可以单独列出:[abc],匹配 'a''b''c'
可以表示字符范围,通过用 '-' 将两个字符连起来:[a-z] 将匹配任何小写 ASCII 字符; 可以指定多个范围:[a-zA-Z] 将匹配所有英文字符。 如果 - 进行了转义 (比如 [a-z])或者它的位置在首位或者末尾(如 [-a][a-]),它就只表示普通字符 '-'
特殊字符在集合中,失去它的特殊含义:[(+*)] 只会匹配这几个文法字符 '(''+''*'')'
字符类如 \w 或者 \S 在集合内可以接受,它们可以匹配的字符由 ASCII 或者 LOCALE 模式决定。
不在集合范围内的字符可以通过取反('^' 作为首字符)来进行匹配:[^a] 将匹配除了 'a' 之外的所有字符。 '^' 如果不在集合首位,就没有特殊含义。
在集合内要匹配一个字符 ']',有两种方法,要么将它进行转义,要么就把它放到集合首位(如 [()[]{}][]()[{}])。
嵌套集合和集合操作支持可能在未来添加。如果有多以的情况发生,将会抛出 FutureWarning
| A|BAB 可以是任意正则表达式,创建一个正则表达式,匹配 A 或者 B。任意个正则表达式可以用 '|' 连接。它可以在集合或组合内使用。 '|' 操作符绝不贪婪:扫描目标字符串时,由 '|' 分隔开的正则样式从左到右进行匹配。当一个样式完全匹配时,这个分支就被接受。即,一旦 A 匹配成功, B 就不再进行匹配,即便它能产生一个更好的匹配。 如果要匹配 '|' 字符,使用 |, 或者把它包含在字符集里 [|]
(…) (组合),匹配括号内的任意正则表达式,并标识出组合的开始和结尾。

定位符

定位符用来描述字符串或单词的边界。

序列 说明
^ (插入符号)匹配字符串的开头, 并且在 MULTILINE 模式也匹配换行后的首个符号。
$ 匹配字符串尾或者在字符串尾的换行符的前一个字符,在 MULTILINE 模式下也会匹配换行符之前的文本。
'foo1\nfoo2\n' 中搜索 foo.$,通常匹配 'foo2',但在 MULTILINE 模式下可以匹配到 'foo1'
'foo\n' 中搜索 $ 会找到两个(空的)匹配:一个在换行符之前,一个在字符串的末尾。
\A 只匹配字符串的开始。相当于默认模式下的 ^
\b 匹配一个单词边界。即,匹配空字符串,但只在单词开始或结尾的位置。
通常 \b 定义为 \w\W 字符之间,或者 \w 和字符串开始/结尾的边界。
如果使用了 LOCALE 标志,则词的边界由当前语言区域设置。
在字符集合内表示退格(如 [\b])。
\B 非单词边界匹配。即,匹配除了单词边界外的任何其他位置。\B\b 的取非。
如果使用了 LOCALE 标志,则词的边界由当前语言区域设置。
\Z 只匹配字符串尾。

重复修饰符(限定符)

  • {m}

    对其之前的正则式指定匹配 m 个重复;少于 m 的话就会导致匹配失败。

贪婪修饰符:

  • *

    对它前面的正则式匹配 0 到任意次重复, 尽量多地匹配字符串。 等价于:{0,}

  • +

    对它前面的子表达式匹配 1 到任意次重复, 尽量多地匹配字符串。 等价于:{1,}

  • ?

    对它前面的子表达式匹配 0 到 1 次重复, 尽量多地匹配字符串。 等价于:{0,1}

  • {m,}

    对它前面的子表达式进行 m 到任意次重复, 尽量多地匹配字符串。

  • {m,n}(中间不要有空白字符)

    对它前面的子表达式进行 m 到 n 次匹配,在 m 和 n 之间取尽量多。

非贪婪修饰符:

  • *?+???{m,}?{m,n}?

    在修饰符之后添加 ? 将使样式以非贪婪方式,或者 :dfn: 最小方式进行匹配; 尽量少的字符将会被匹配。


扩展标记法

  • (?…)``'?' 仅跟随 '(' 并无含义。'?' 后面的第一个字符决定了这个构建采用什么样的语法。这种扩展通常并不创建新的组合; (?P<name>...) 是唯一的例外。

  • (?aiLmsux)

    (? 后带 'a''i''L''m''s''u''x' 中的一个或多个。(?aimsx) 将会匹配空字符串。

    这些字符代表内联标记(与 re 模块中的 RegexFlag 标志常量对应)。

    • 'a' —— re.A 模式;

    • 'i' —— re.I 模式;

    • 'L' —— re.L 模式;

    • 'm' —— re.M 模式;

    • 's' —— re.S 模式;

    • 'u' —— re.U 模式;

    • 'x' —— re.X 模式。

  • (?:…)

    正则括号的非捕获版本。 匹配在括号内的任何正则表达式,但该分组所匹配的子字符串不能在执行匹配后被获取或是之后在模式中被引用。

  • (?aiLmsux-imsx:…)``'?' 后面 '-' 前面带 'a''i''L''m''s''u''x' 中的 0 个或多个。'-' 后面 ':' 前面带 'i''m''s''x' 中的一到多个。表示设置或者去除('-' 后指定去除的标记)相应标记。

    (?aiLmsux) 一样,这些字符分别代表了不同的内联标记。

    'a''L''u' 作为内联标记是相互排斥的, 所以它们不能结合在一起,或者跟随 '-' 。 当他们中的某个出现在内联组中,它就覆盖了括号组内的匹配模式。Python3.7 接受 'a''L''u' 存在于一个组合。 这种方式只覆盖组合内匹配,括号外的匹配模式不受影响。

  • (?P<name>…)

    (命名组合)类似正则组合,但是匹配到的子串组在外部可以通过定义的 name 来获取的(也可以通过数字获取)。组合名必须是有效的 Python 标识符,并且每个组合名只能用一个正则表达式定义,只能定义一次。 命名组合可以在三种上下文中引用:

    引用组合 “quote” 的上下文 引用方法
    在正则式自身内 (?P=quote)\1
    处理匹配对象 m m.group('quote')m.end('quote')(等)
    传递到 re.sub() 里的 repl 参数中 \g<quote>\g<1>\1
  • (?P=name)

    反向引用一个命名组合;它匹配前面名为 name 的命名组中匹配到的串同样的字串(如上所示)。

  • (?#…)

    注释,里面的内容会被忽略。

  • (?=…)

    lookahead assertion,匹配 的内容,但是并不消费样式的内容。如,abc(?=def)'abc' 后面是 'def' 的时候,才匹配 'abc'

  • (?!…)

    negative lookahead assertion(前视取反),匹配 不符合的情况。如,abc(?!def)'abc' 后面不是 'def' 的时候,才匹配 'abc'

  • (?<=…)

    :dfn:positive lookbehind assertion(正向后视断定),匹配字符串的当前位置,它的前面匹配 的内容到当前位置。如,(?<=abc)def'def' 前面是 'abc' 时匹配 'def',该样式是从 'd' 开始往回搜索的。 包含的匹配样式必须是定长的( abca|b 是允许的,但是 a*a{3,4} 不可以)。

  • (?<!…)

    negative lookbehind assertion (后视断定取非),匹配当前位置之前不是 的样式。

    包含的样式匹配必须是定长的。

    由 negative lookbehind assertion 开始的样式可以从字符串搜索开始的位置进行匹配。

  • (?(id/name)yes-pattern|no-pattern)

    如果给定的 idname 存在,将会尝试匹配 yes-pattern ,否则就尝试匹配 no-patternno-pattern 可选,可以被忽略)。


\\+普通字符

\ + (ASCII 数字或字母):

序列 说明
\number 匹配数字代表的组合。每个正则表达式中的括号是一个组合,组合从 1 开始编号。
如:(.+) \1 匹配 'the the' 或者 '55 55'
这个特殊序列只能用于匹配前面 99 个组合。
如果 number 的第一个数位是 0, 或者 number 是三个八进制数,它将不会被看作是一个组合,而是八进制的数字值。
\A 只匹配字符串开始。
\b (单词边界定位符)匹配空字符串,但只在单词开始或结尾的位置。
在字符集合内表示退格(如 [\b])。
\B (非单词边界定位符)匹配空字符串,但不能在词的开头或者结尾。
\d 对于 Unicode(str)样式:
匹配任何 Unicode 十进制数(就是在 Unicode 字符目录 [Nd] 里的字符,包括了 [0-9] ,和很多其他的数字字符)。如果设置了 ASCII 标志,就只匹配 [0-9]
对于8位(bytes)样式:
匹配任何十进制数([0-9])。
\D 匹配任何非十进制数字的字符(\d 取非)。
如果设置了 ASCII 标志,就相当于 [^0-9]
\s 对于 Unicode(str)样式:
匹配任何 Unicode 空白字符(包括 [ \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 词语的字符,包含了可以构成词语的绝大部分字符,也包括数字和下划线。如果设置了 ASCII 标志,就只匹配 [a-zA-Z0-9_]
对于8位(bytes)样式:
匹配 ASCII 字符中的数字和字母和下划线,就是 [a-zA-Z0-9_] 。如果设置了 LOCALE 标记,就匹配当前语言区域的数字和字母和下划线。
\W 匹配非单词字符的字符(与 \w 正相反)。
如果使用了 ASCII 标志,就等价于 [^a-zA-Z0-9_]
如果使用了 LOCALE 标志,则会匹配当前区域中既非字母数字也非下划线的字符。
\Z 只匹配字符串尾。
如果普通字符不是 ASCII 数位或者 ASCII 字母,那么正则样式将匹配第二个字符(如,\$ 匹配字符 '$')。

绝大部分 Python 的标准转义字符也被正则表达式分析器支持:

\a      \b      \f      \n
\N      \r      \t      \u
\U      \v      \x      \\

'\u''\U''\N' 转义序列只在 Unicode 模式中可被识别。 在 bytes 模式中它们会导致错误。未知的 ASCII 字母转义序列保留在未来使用,会被当作错误来处理。

八进制转义包含为一个有限形式。如果首位数字是 0, 或者有三个八进制数位,那么就认为它是八进制转义。其他的情况,就看作是组引用。对于字符串文本,八进制转义最多有三个数位长。


re 模块

Python 的 re 模块提供了与 Perl 语言类似的正则表达式匹配操作。


函数

匹配一项

re 模块中,有三个函数用于查找并返回一个匹配对象:

  1. re.match() —— 返回一个从字符串的起始位置匹配的对象。

  2. re.search() —— 返回整个字符串中任意位置第一个成功的匹配。

  3. re.fullmatch() —— 整个字符串与正则表达式完全匹配。


match() 函数

re.match() 尝试从字符串的起始位置匹配一个模式,其语法如下:

re.match(pattern, string, flags=0)

参数:

参数 描述
pattern 匹配的正则表达式。
string 要匹配的字符串。
flags 标志位,用于控制正则表达式的匹配方式。

返回值:

匹配成功,re.match() 函数返回一个匹配对象(Match);否则返回 None

Example:

>>> import re
>>> re.match('abc', 'abcdefg')  # 在起始位置匹配
<_sre.SRE_Match object; span=(0, 3), match='abc'>
>>> re.match('efg', 'abcdefg')  # 不在起始位置匹配
None

search() 函数

re.search() 扫描整个字符串并返回第一个成功的匹配,其语法如下:

re.search(pattern, string, flags=0)

参数用法与 re.match() 类似。匹配成功,re.search() 方法返回一个匹配对象(Match);否则返回 None

Example:

>>> import re
>>> re.search('abc', 'abcdefg')  # 在起始位置匹配
<_sre.SRE_Match object; span=(0, 3), match='abc'>
>>> re.search('efg', 'abcdefg')  # 不在起始位置匹配
<_sre.SRE_Match object; span=(4, 7), match='efg'>

fullmatch() 函数

fullmatch() 将整个字符串与正则表达式匹配,其语法如下:

re.fullmatch(pattern, string, flags=0)

参数用法与 re.match() 类似。如果 stringpattern 完全匹配,那么返回一个匹配对象(Match);否则返回 None

Example:

>>> import re
>>> re.fullmatch('abc', 'abcdefg')    # 在起始位置匹配
None
>>> re.fullmatch('abcdefg', 'abcdefg')  # 匹配整个字符串
<_sre.SRE_Match object; span=(0, 7), match='abcdefg'>

匹配多项

有两个函数用于查找并返回匹配的多个匹配对象:

  1. re.findall —— 在字符串的任意位置匹配,并返回一个包含了所有匹配对象的列表。

  2. re.finditer —— 在字符串的任意位置匹配,并返回一个包含了所有匹配对象的迭代器。


finall()

finall() 在字符串中找到正则表达式所匹配的所有子串,其语法如下:

re.findall(pattern, string, flags=0)

参数:

参数 描述
pattern 匹配的正则表达式。
string 要匹配的字符串。
flags 标志位,用于控制正则表达式的匹配方式。

返回值:

返回一个列表,包含了所有匹配对象;如果没有任何匹配项,则返回空列表。


finditer()

finall() 类似,其语法如下:

re.finditer(pattern, string, flags=0)

该函数返回的是迭代器。

如果可能存在大量的匹配项的话,建议使用 finditer()


split() 正则分割

re.split() 按照能够匹配的子串对字符串进行分割,其语法如下:

re.split(pattern, string[, maxsplit=0, flags=0])

参数:

参数 描述
pattern 匹配的正则表达式。
string 要匹配的字符串。
maxsplit 最大分割次数,maxsplit=1 分割一次,默认为 0,不限制次数。
flags 标志位,用于控制正则表达式的匹配方式。

返回值:

返回一个用 patterm 模式匹配的字符分割的字符串列表。如果查找不到任何匹配,则返回一个仅包含 string 的列表。

str 模块下也有一个 split() 函数,但它并不支持正则分割。


替换

有两个替换函数:re.sub()re.subn()

re.sub(pattern, repl, string, count=0, flags=0)
re.subn(pattern, repl, string, count=0, flags=0)

参数:

参数 描述
pattern 匹配的正则表达式。
repl 替换内容,可以是字符串,也可以是函数。如果 repl 为函数,只能有一个匹配对象作为参数。
string 要匹配的字符串。
count 最大替换次数。
flags 标志位,用于控制正则表达式的匹配方式。

repl 替换掉 string 中被 pattern 匹配的字符。

返回值:

re.sub() 返回一个替换后的字符串。如果 string 中没有任何匹配项,则返回 string

re.subn() 返回一个元组,包含了替换后的字符串和替换次数:(str, n)


excape() 转义函数

re.exvape() 函数可以转义参数 pattern 中的特殊字符。

re.exvape(pattern)

Example:

>>> print(re.escape('http://www.python.org'))
http://www\.python\.org

Python3.3:_ 不再被转义。

Python3.7:只有在正则表达式中具有特殊含义的字符才会被转义。 因此, !"%',/:;<’、=>’、@ 和 ` 将不再会被转义。

使用 re.exvape() 函数很容易出现转义错误的问题,所以并不建议使用它转义。


purge() 清除正则表达式缓存

re.purge() 用于清除正则表达式的缓存。它没有参数,没有返回值。


RegexFlag 标志常量

  • re.ASCII:

    • 简写:re.A

    • \w, \W, \b, \B, \d, \D, \s\S 只匹配 ASCII 编码支持的字符,而不是 Unicode。这只对 Unicode 样式(Python3 默认)有效,会被 byte 样式忽略。

    • Example:

      >>> re.search(r'\w+', '中文字符和ASCII', re.A)
      <_sre.SRE_Match object; span=(5, 10), match='ASCII'>
      
    • 对应内联标记:(?a)

  • re.DEBUG:

    • 显示编译时的 debug 信息,没有内联标记。

    • Example:

      >>> re.search(r'.*', '显示debug信息', re.DEBUG)
      MAX_REPEAT 0 MAXREPEAT
        ANY None
      <_sre.SRE_Match object; span=(0, 9), match='显示debug信息'>
      
    • 对应内联标记:(?i)

  • re.IGNORECASE:

    • 简写:re.I

    • 进行忽略大小写匹配。

    • Example:

      >>> re.findall(r'[a-z]', '大写字母:ABCDE 小写字母:abcde', re.I)
      ['A', 'B', 'C', 'D', 'E', 'a', 'b', 'c', 'd', 'e']
      
  • re.LOCALE:

    • 简写:re.L

    • 语言依赖,由当前语言区域决定 \w, \W, \b, \B 和大小写敏感匹配。这个标记只能对 byte 样式有效。这个标记官方并不推荐使用,因为语言区域机制很不可靠,它一次只能处理一个 “习惯”,而且只对 8 位字节有效。

    • 对应内联标记:(?L)

  • re.MULTILINE:

    • 简写:re.M

    • 多行模式,样式字符 '^' 匹配每一个行开始(字符串的开始和换行符后紧跟的符号);样式字符 '$' 匹配每一个行结尾(字符串结尾和换行符前面的符号)。

      默认情况下不支持换行符特性,'^' 匹配字符串开始,'$' 匹配字符串结尾。

    • Example:

      >>> re.findall(r'^.*$', '第1行\n第2行\n第3行', re.M)
      ['第1行', '第2行', '第3行']
      
    • 对应内联标记:(?m)

  • re.DOTALL:

    • 简写:re.S

    • '.' 特殊字符匹配全部字符,包括换行符。

      默认情况下,'.' 仅匹配除了换行符的其他任意字符。

    • 对应内联标记:(?s)

  • re.VERBOSE:

    • 简写:re.X

    • 冗长模式,允许在正则表达式中换行和添加注释。 该模式下空白符号会被忽略,除非在一个字符集合中或者由反斜杠转义,或者在 *?(?:(?P<…> 分组之内。 当一个行内有 # 不在字符集和转义序列,那么它之后的所有字符都是注释。

    • Example:

      >>> re.search(r'''\d +  # the integral part
      ...               \.    # the decimal point
      ...               \d *  # some fractional digits''',
      ...           '圆周率:3.14', re.X)
      <_sre.SRE_Match object; span=(4, 8), match='3.14'>
      
    • 对应内联标记:(?x)

  • re.UNICODE:

    • 简写:re.U

    • 匹配 Unicode 编码支持的字符,是 Python3 默认的字符串模式。虽然保留着,但对 Python3 来说是个冗余的常量。

  • re.TEMPLATE:

    • 简写:re.T

    • re 模块的源码是这样描述该常量的(官方文档中并没有具体的描述):

      TEMPLATE = T = sre_compile.SRE_FLAG_TEMPLATE # disable backtracking
      

正则对象 Pattern

使用 compile()template() 可以将正则表达式编译为正则表达式对象(Pattern,正则对象)。

re.compile() 的语法如下:

re.compile(pattern, flags=0)
参数 描述
pattern 要转化为正则对象的正则表达式。
flags 标志位,用于控制正则表达式的匹配方式。 可以通过位的 OR('|')操作来结合多个模式。

Example:

>>> pattern_obj = re.compile(r'abc')
>>> pattern_obj.search('abcdefg')
<_sre.SRE_Match object; span=(0, 3), match='abc'>

使用正则对象和函数:

  1. 正则对象和函数是一致的。

    模块的底层实现中,re.compile() 与其他 re 函数内部调用的是同一个函数 re._compile()

  2. 如果需要多次使用某个正则表达式的话,使用 re.compile() 和保存这个正则对象以便复用,可以让程序更加高效。通过 re.compile() 编译后的样式,和模块级的函数会被缓存。


正则对象方法

正则对象支持以下方法:

方法 说明
Pattern.search(string[, pos[, endpos]]) 扫描整个 string 寻找第一个匹配的位置, 并返回一个相应的匹配对象(Match)。如果没有匹配,就返回 None
pos —— 字符串中开始搜索的位置索引,默认为 0,它不完全等价于字符串切片。^ 样式字符匹配行开头,但不会匹配索引规定开始的位置。
endpos —— 字符串搜索的结束。只有从 posendpos - 1 的字符会被匹配。
如果 endpos 小于 pos,就不会有匹配产生。
pattern_obj.search(string, 0, 50)等价于pattern_obj.search(string[:50], 0)`。
Pattern.match(string[, pos[, endpos]]) 如果 string 的开始位置能够找到这个正则样式 Pattern 的任意个匹配,就返回一个相应的匹配对象(Match)。如果不匹配,就返回 None
可选参数 posendpos 指定 string 的查找范围,与 Pattern.search() 含义相同。
Pattern.fullmatch(string[, pos[, endpos]]) 如果整个 string 匹配这个正则表达式,就返回一个相应的匹配对象(Match)。如果不匹配,就返回 None
可选参数 posendpos 指定 string 的查找范围。
Pattern.findall(string[, pos[, endpos]]) 类似 re.findall(),使用了编译后样式,在 string 中找到 Pattern 所匹配的所有子串,以列表形式返回所有匹配项。
可选参数 posendpos 指定 string 的查找范围。
Pattern.finditer(string[, pos[, endpos]]) 类似函数 finiter() , 使用了编译后样式,在 string 中找到 Pattern 所匹配的所有子串,以迭代器形式返回所有匹配项。
可选参数 posendpos 指定 string 的查找范围。
Pattern.split(string, maxsplit=0) 等价于 split() 函数,使用了编译后的样式,按照能够匹配的子串对字符串进行分割。
maxsplit —— 最大分割次数。
Pattern.sub(repl, string, count=0) 等价于 sub() 函数,使用了编译后的样式,使用 repl 替换掉 string 中被 Pattern 匹配的字符。
count —— 最大替换次数。
返回一个替换后的字符串。如果 string 中没有任何匹配项,则返回 string
Pattern.subn(repl, string, count=0) 等价于 subn() 函数,使用了编译后的样式,使用 repl 替换掉 string 中被 Pattern 匹配的字符。
count —— 最大替换次数。
返回一个元组,包含了替换后的字符串和替换次数。

正则对象属性

属性 说明
Pattern.flags 正则匹配标记。
可以传递给 compile() 的参数。任何 (?…) 内联标记,隐性标记(re.U)的结合。
Pattern.groups 捕获到的模式串中组的数量。
Pattern.groupindex 映射由 (?P<id>) 定义的命名符号组合和数字组合的字典。如果没有符号组,那字典就是空的。
Pattern.pattern 编译对象的原始样式字符串。

匹配对象

匹配对象(Match)是调用 re 模块中的函数或方法匹配后返回的对象。

匹配对象总是有一个布尔值 True。如果没有匹配的话 re.match()re.search() 返回 None。可以简单的用 if 语句来判断是否匹配:

>>> if re.search(r'a', 'abc'):
...     print(True)
...
True
>>> if re.search(r'd', 'abc'):
...     print(True)
... else:
...     print(False)
...
False

匹配对象方法

匹配对象支持以下方法:

  • Match.expand(template)

    • template 进行反斜杠('\')转义替换并且返回。
  • Match.group([group1, ...])

    • 返回一个或者多个匹配的子组。

    • 如果只有一个参数,结果就是一个字符串; 如果有多个参数,结果就是一个元组(每个参数对应一个项); 如果没有参数,group1 默认为 0(整个匹配都被返回)。

    • 如果一个 groupN 参数值为 0,相应的返回值就是整个匹配字符串; 如果它是一个范围 [1..99],结果就是相应的括号组字符串。

    • 如果一个组号是负数,或者大于样式中定义的组数,会抛出一个 IndexError

    • Example:

      >>> m = re.match(r'(\w+) (\w+)', 'Python PHP Java C++')
      >>> m.group()    # 返回整个匹配
      'Python PHP'
      >>> m.group(1)    # 返回第一个括号组
      'Python'
      >>> m.group(2)    # 返回第二个括号组
      'PHP'
      >>> m.group(1, 2)  # 多个参数返回一个元组
      ('Python', 'PHP')
      
    • 如果正则表达式使用了 (?P<name>…) 语法, groupN 参数可以是索引值,也可以是组名。

      >>> m = re.match(r'(?P<name_1>\w+) (?P<name_2>\w+)', 'Python PHP')
      >>> m.group('name_1', 'name_2')
      ('Python', 'PHP')
      >>> m.group(1, 2)
      ('Python', 'PHP')
      
    • 如果一个组包含在样式的一部分,并被匹配多次,就返回最后一个匹配。

      >>> m = re.match(r'(..)+', 'a1b2c3')
      >>> m.group(1)
      'c3'
      
  • Match.getitem(g)

    • Python3.6 新增功能。

    • 等价于 m.group(g),允许更方便地引用一个匹配。

      >>> m = re.match(r'(?P<name_1>\w+) (?P<name_2>\w+)', 'Python PHP')
      >>> m[0]
      'Python PHP'
      >>> m[1]
      'Python'
      >>> m[2]
      'PHP'
      
  • Match.groups(default=None)

    • 返回一个元组,包含所有匹配的子组,在样式中出现的从 1 到任意多的组合。default 参数用于不参与匹配的情况,默认为 None

    • Example: 使小数部分可选,那么不是所有的组都会参与到匹配当中。这些组合默认会返回一个 None ,除非指定了 default 参数。

      >>> m = re.match(r'(\d+)\.(\d+)', '3.14')
      >>> m.groups()
      ('3', '14')
      
      >>> m = re.match(r"(\d+)\.?(\d+)?", '3')
      >>> m.groups()    # 第二个子组默认为 None
      ('3', None)
      >>> m.groups('0')  # 第二个子组被设置为指定的默认值 '0'
      ('3', '0')
      
  • Match.groupdict(default=None)

    • 返回一个字典,包含了所有的命名子组。key 就是组名。 default 参数用于不参与匹配的组合;默认为 None

    • Example:

      >>> m = re.match(r'(?P<name_1>\w+) (?P<name_2>\w+)', 'Python PHP')
      >>> m.groupdict()
      {'name_1': 'Python', 'name_2': 'PHP'}
      
  • Match.start([group])Match.end([group])

    • 返回 group 匹配到的字串在原字符串的开始和结束索引。group 默认为 0(意思是整个匹配的子串)。如果 group 存在,但未产生匹配,就返回 -1

    • 从 email 地址中移除掉 remove_this

      >>> email = "tony@tiremove_thisger.net"
      >>> m = re.search("remove_this", email)
      >>> email[:m.start()] + email[m.end():]
      'tony@tiger.net'
      
  • Match.span([group])

    • 对于一个匹配 m , 返回一个二元组 (m.start(group), m.end(group)) 。 如果 group 没有在这个匹配中,就返回 (-1, -1)group 默认为 0,就是整个匹配。