【python】python的正则表达式 re

 ps:本文摘自互联网,以为结构很好,讲的也很清晰。记下,备查。python

延伸阅读:python的 内建函数 和 subprocess 。此文是本系列的第三篇文章了,和以前同样,内容出自官方文档,可是会有本身的理解,并不是单纯的翻译。因此,若是我理解有误,欢迎指正,谢谢。git

本模块提供了和Perl里的正则表达式相似的功能,不关是正则表达式自己仍是被搜索的字符串,均可以是Unicode字符,这点不用担忧,python会处理地和Ascii字符同样漂亮。正则表达式

正则表达式使用反斜杆(\)来转义特殊字符,使其能够匹配字符自己,而不是指定其余特殊的含义。这可能会和python字面意义上的字符串转义相冲突,这也许有些使人费解。好比,要匹配一个反斜杆自己,你也许要用'\\\\'来作为正则表达式的字符串,由于正则表达式要是\\,而字符串里,每一个反斜杆都要写成\\。express

你也能够在字符串前加上 r 这个前缀来避免部分疑惑,由于 r 开头的python字符串是 raw 字符串,因此里面的全部字符都不会被转义,好比r'\n'这个字符串就是一个反斜杆加上一字母n,而'\n'咱们知道这是个换行符。所以,上面的'\\\\'你也能够写成r'\\',这样,应该就好理解不少了。能够看下面这段:安全

>>> import re函数

>>> s = '\x5c'  #0x5c就是反斜杆测试

>>> print sthis

\spa

>>> re.match('\\\\', s)  #这样能够匹配.net

<_sre.SRE_Match object at 0xb6949e20>

>>> re.match(r'\\', s)  #这样也能够

<_sre.SRE_Match object at 0x80ce2c0>

>>> re.match('\\', s)  #可是这样不行

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

  File "/usr/lib/python2.6/re.py", line 137, in match

    return _compile(pattern, flags).match(string)

  File "/usr/lib/python2.6/re.py", line 245, in _compile

    raise error, v # invalid expression

sre_constants.error: bogus escape (end of line)

>>> 

另外值得一提的是,re模块的方法,大多也就是RegexObject对象的方法,二者的区别在于执行效率。这个在最后再展开吧。

正则表达式语法

正则表达式(RE)指定一个与之匹配的字符集合;本模块所提供的函数,将能够用来检查所给的字符串是否与指定的正则表达式匹配。

正则表达式能够被链接,从而造成新的正则表达式;例如A和B都是正则表达式,那么AB也是正则表达式。通常地,若是字符串p与A匹配,q与B匹配的话,那么字符串pq也会与AB匹配,但A或者B里含有边界限定条件或者命名组操做的状况除外。也就是说,复杂的正则表达式能够用简单的链接而成。

正则表达式能够包含特殊字符和普通字符,大部分字符好比'A','a'和'0'都是普通字符,若是作为正则表达式,它们将匹配它们自己。因为正则表达式能够链接,因此链接多个普通字符而成的正则表达式last也将匹配'last'。(后面将用不带引号的表示正则表达式,带引号的表示字符串)

下面就来介绍正则表达式的特殊字符:

'.'

点号,在普通模式,它匹配除换行符外的任意一个字符;若是指定了 DOTALL 标记,匹配包括换行符之内的任意一个字符。

'^'

尖尖号,匹配一个字符串的开始,在 MULTILINE 模式下,也将匹配任意一个新行的开始。

'$'

美圆符号,匹配一个字符串的结尾或者字符串最后面的换行符,在 MULTILINE 模式下,也匹配任意一行的行尾。也就是说,普通模式下,foo.$去搜索'foo1\nfoo2\n'只会找到’foo2′,可是在 MULTILINE 模式,还能找到 ‘foo1′,并且就用一个 $ 去搜索'foo\n'的话,会找到两个空的匹配:一个是最后的换行符,一个是字符串的结尾,演示:

>>> re.findall('(foo.$)', 'foo1\nfoo2\n')

['foo2']

>>> re.findall('(foo.$)', 'foo1\nfoo2\n', re.MULTILINE)

['foo1', 'foo2']

>>> re.findall('($)', 'foo\n')

['', '']

'*'

星号,指定将前面的RE重复0次或者任意屡次,并且老是试图尽可能屡次地匹配。

'+'

加号,指定将前面的RE重复1次或者任意屡次,并且老是试图尽可能屡次地匹配。

'?'

问号,指定将前面的RE重复0次或者1次,若是有的话,也尽可能匹配1次。

*?, +?, ??

从前面的描述能够看到'*','+'和'?'都是贪婪的,但这也许并非咱们说要的,因此,能够在后面加个问号,将策略改成非贪婪,只匹配尽可能少的RE。示例,体会二者的区别:

>>> re.findall('<(.*)>', '<H1>title</H1>')

['H1>title</H1']

>>> re.findall('<(.*?)>', '<H1>title</H1>')

['H1', '/H1']

{m}

m是一个数字,指定将前面的RE重复m次。

{m,n}

m和n都是数字,指定将前面的RE重复m到n次,例如a{3,5}匹配3到5个连续的a。注意,若是省略m,将匹配0到n个前面的RE;若是省略n,将匹配n到无穷多个前面的RE;固然中间的逗号是不能省略的,否则就变成前面那种形式了。

{m,n}?

前面说的{m,n},也是贪婪的,a{3,5}若是有5个以上连续a的话,会匹配5个,这个也能够经过加问号改变。a{3,5}?若是可能的话,将只匹配3个a。

'\'

反斜杆,转义'*','?'等特殊字符,或者指定一个特殊序列(下面会详述)

因为以前所述的缘由,强烈建议用raw字符串来表述正则。

[]

方括号,用于指定一个字符的集合。能够单独列出字符,也能够用'-'链接起止字符以表示一个范围。特殊字符在中括号里将失效,好比[akm$]就表示字符'a','k','m',或'$',在这里$也变身为普通字符了。[a-z]匹配任意一个小写字母,[a-zA-Z0-9]匹配任意一个字母或数字。若是你要匹配']'或'-'自己,你须要加反斜杆转义,或者是将其置于中括号的最前面,好比[]]能够匹配']'

你还能够对一个字符集合取反,以匹配任意不在这个字符集合里的字符,取反操做用一个'^'放在集合的最前面表示,放在其余地方的'^'将不会起特殊做用。例如[^5]将匹配任意不是'5'的字符;[^^]将匹配任意不是'^'的字符。

注意:在中括号里,+、*、(、)这类字符将会失去特殊含义,仅做为普通字符。反向引用也不能在中括号内使用。

'|'

管道符号,A和B是任意的RE,那么A|B就是匹配A或者B的一个新的RE。任意个数的RE均可以像这样用管道符号间隔链接起来。这种形式能够被用于中(后面将详述)。对于目标字符串,被'|'分割的RE将自左至右一一被测试,一旦有一个测试成功,后面的将再也不被测试,即便后面的RE可能能够匹配更长的串,换句话说,'|'操做符是非贪婪的。要匹配字面意义上的'|',能够用反斜杆转义:\|,或是包含在反括号内:[|]。

(...)

匹配圆括号里的RE匹配的内容,并指定的开始和结束位置。组里面的内容能够被提取,也能够采用\number这样的特殊序列,被用于后续的匹配。要匹配字面意义上的'('和')',能够用反斜杆转义:\(、\),或是包含在反括号内:[(]、[)]。

(?...)

这是一个表达式的扩展符号。'?'后的第一个字母决定了整个表达式的语法和含义,除了(?P...)之外,表达式不会产生一个新的组。下面介绍几个目前已被支持的扩展:

(?iLmsux)

'i'、'L'、'm'、's'、'u'、'x'里的一个或多个字母。表达式不匹配任何字符,可是指定相应的标志:re.I(忽略大小写)、re.L(依赖locale)、re.M(多行模式)、re.S(.匹配全部字符)、re.U(依赖Unicode)、re.X(详细模式)。关于各个模式的区别,下面会有专门的一节来介绍的。使用这个语法能够代替在re.compile()的时候或者调用的时候指定flag参数。

例如,上面举过的例子,能够改写成这样(和指定了re.MULTILINE是同样的效果):

>>> re.findall('(?m)(foo.$)', 'foo1\nfoo2\n')

['foo1', 'foo2']

另外,还要注意(?x)标志若是有的话,要放在最前面。

(?:...)

匹配内部的RE所匹配的内容,可是不创建

(?P<name>...)

和普通的圆括号相似,可是子串匹配到的内容将能够用命名的name参数来提取。组的name必须是有效的python标识符,并且在本表达式内不重名。命名了的组和普通组同样,也用数字来提取,也就是说名字只是个额外的属性。

演示一下:

>>> m=re.match('(?P<var>[a-zA-Z_]\w*)', 'abc=123')

>>> m.group('var')

'abc'

>>> m.group(1)

'abc'

(?P=name)

匹配以前以name命名的组里的内容。

演示一下:

>>> re.match('<(?P<tagname>\w*)>.*</(?P=tagname)>', '<h1>xxx</h2>')  #这个不匹配

>>> re.match('<(?P<tagname>\w*)>.*</(?P=tagname)>', '<h1>xxx</h1>')  #这个匹配

<_sre.SRE_Match object at 0xb69588e0>

(?#...)

注释,圆括号里的内容会被忽略。

(?=...)

若是 ... 匹配接下来的字符,才算匹配,可是并不会消耗任何被匹配的字符。例如 Isaac (?=Asimov) 只会匹配后面跟着 'Asimov' 的 'Isaac ',这个叫作“前瞻断言”。

(?!...)

和上面的相反,只匹配接下来的字符串匹配 ... 的串,这叫作“反前瞻断言”。

(?<=...)

只有当当前位置以前的字符串匹配 ... ,整个匹配才有效,这叫“后顾断言”。(?<=abc)def会找到 'abcdef',由于会后向查找3个字符,看是否为abc。因此内置的子RE,须要是固定长度的,好比能够是abc、a|b,但不能是a*、a{3,4}。注意这种RE永远不会匹配到字符串的开头。举个例子,找到连字符('-')后的单词:

>>> m = re.search('(?<=-)\w+', 'spam-egg')

>>> m.group(0)

'egg'

(?<!...)

同理,这个叫作“反后顾断言”,子RE须要固定长度的,含义是前面的字符串不匹配 ... 整个才算匹配。

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

若有由id或者name指定的组存在的话,将会匹配yes-pattern,不然将会匹配no-pattern,一般状况下no-pattern也能够省略。例如:()能够匹配 '<user@host.com>' 和 'user@host.com',可是不会匹配 '<user@host.com'。

下面列出以'\'开头的特殊序列。若是某个字符没有在下面列出,那么RE的结果会只匹配那个字母自己,好比,\$只匹配字面意义上的'$'。

\number

匹配number所指的组相同的字符串。组的序号从1开始。例如:(.+) \1能够匹配'the the'和'55 55',但不匹配'the end'。这种序列在一个正则表达式里最多能够有99个,若是number以0开头,或是有3位以上的数字,就会被当作八进制表示的字符了。同时,这个也不能用于方括号内。

\A

只匹配字符串的开始。

\b

匹配单词边界(包括开始和结束),这里的“单词”,是指连续的字母、数字和下划线组成的字符串。注意,\b的定义是\w和\W的交界,因此精确的定义有赖于UNICODE和LOCALE这两个标志位。

\B

和\b相反,\B匹配非单词边界。也依赖于UNICODE和LOCALE这两个标志位。

\d

未指定UNICODE标志时,匹配数字,等效于:[0-9]。指定了UNICODE标志时,还会匹配其余Unicode库里描述为字符串的符号。便于理解,举个例子(好不容易找的例子啊,呵呵):

#\u2076\和u2084分别是上标的6和下标的4,属于unicode的DIGIT

>>> unistr = u'\u2076\u2084abc'

>>> print unistr

⁶₄abc

>>> print re.findall('\d+', unistr, re.U)[0]

⁶₄

\D

和\d相反,很少说了。

\s

当未指定UNICODE和LOCALE这两个标志位时,匹配任何空白字符,等效于[ \t\n\r\f\v]。若是指定了LOCALE,则还要加LOCALE相关的空白字符;若是指定了UNICODE,还要加上UNICODE空白字符,如较常见的空宽度链接空格(\uFEFF)、零宽度非链接空格(\u200B)等。

\S

和\s相反,也很少说。

\w

当未指定UNICODE和LOCALE这两个标志位时,等效于[a-zA-Z0-9_]。当指定了LOCALE时,为[0-9_]加上当前LOCAL指定的字母。当指定了UNICODE时,为[0-9_]加上UNICODE库里的全部字母。

\W

和\w相反,很少说。

\Z

只匹配字符串的结尾。

匹配之于搜索

python提供了两种基于正则表达式的操做:匹配(match)从字符串的开始检查字符串是否个正则匹配。而搜索(search)检查字符串任意位置是否有匹配的子串(perl默认就是如此)。

注意,即便search的正则以'^'开头,match和search也仍是有许多不一样的。

>>> re.match("c", "abcdef")  # 不匹配

>>> re.search("c", "abcdef") # 匹配

<_sre.SRE_Match object at ...>

模块的属性和方法

re.compile(pattern[, flags])

把一个正则表达式pattern编译成正则对象,以即可以用正则对象的matchsearch方法。

获得的正则对象的行为(也就是模式)能够用flags来指定,值能够由几个下面的值OR获得。

如下两段内容在语法上是等效的:

prog = re.compile(pattern)

result = prog.match(string)

result = re.match(pattern, string)

区别是,用了re.compile之后,正则对象会获得保留,这样在须要屡次运用这个正则对象的时候,效率会有较大的提高。再用上面用过的例子来演示一下,用相同的正则匹配相同的字符串,执行100万次,就体现出compile的效率了(数据来自我那1.86G CPU的神舟本本):

>>> timeit.timeit(

...     setup='''import re; reg = re.compile('<(?P<tagname>\w*)>.*</(?P=tagname)>')''',

...     stmt='''reg.match('<h1>xxx</h1>')''',

...     number=1000000)

1.2062149047851562

>>> timeit.timeit(

...     setup='''import re''',

...     stmt='''re.match('<(?P<tagname>\w*)>.*</(?P=tagname)>', '<h1>xxx</h1>')''',

...     number=1000000)

4.4380838871002197

re.I

re.IGNORECASE

让正则表达式忽略大小写,这样一来,[A-Z]也能够匹配小写字母了。此特性和locale无关。

re.L

re.LOCALE

让\w、\W、\b、\B、\s和\S依赖当前的locale。

re.M

re.MULTILINE

影响'^'和'$'的行为,指定了之后,'^'会增长匹配每行的开始(也就是换行符后的位置);'$'会增长匹配每行的结束(也就是换行符前的位置)。

re.S

re.DOTALL

影响'.'的行为,平时'.'匹配除换行符之外的全部字符,指定了本标志之后,也能够匹配换行符。

re.U

re.UNICODE

让\w、\W、\b、\B、\d、\D、\s和\S依赖Unicode库。

re.X

re.VERBOSE

运用这个标志,你能够写出可读性更好的正则表达式:除了在方括号内的和被反斜杠转义的之外的全部空白字符,都将被忽略,并且每行中,一个正常的井号后的全部字符也被忽略,这样就能够方便地在正则表达式内部写注释了。也就是说,下面两个正则表达式是等效的:

a = re.compile(r"""\d +  # the integral part

                   \.    # the decimal point

                   \d *  # some fractional digits""", re.X)

b = re.compile(r"\d+\.\d*")

re.search(pattern, string[, flags])

扫描string,看是否有个位置能够匹配正则表达式pattern。若是找到了,就返回一个MatchObject的实例,不然返回None,注意这和找到长度为0的子串含义是不同的。搜索过程受flags的影响。

re.match(pattern, string[, flags])

若是字符串string的开头和正则表达式pattern匹配的话,返回一个相应的MatchObject的实例,不然返回None

注意:要在字符串的任意位置搜索的话,须要使用上面的search()

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

用匹配pattern的子串来分割string,若是pattern里使用了圆括号,那么被pattern匹配到的串也将做为返回值列表的一部分。若是maxsplit不为0,则最多被分割为maxsplit个子串,剩余部分将整个地被返回。

>>> re.split('\W+', 'Words, words, words.')

['Words', 'words', 'words', '']

>>> re.split('(\W+)', 'Words, words, words.')

['Words', ', ', 'words', ', ', 'words', '.', '']

>>> re.split('\W+', 'Words, words, words.', 1)

['Words', 'words, words.']

若是正则有圆括号,而且能够匹配到字符串的开始位置的时候,返回值的第一项,会多出一个空字符串。匹配到字符结尾也是一样的道理:

>>> re.split('(\W+)', '...words, words...')

['', '...', 'words', ', ', 'words', '...', '']

注意,split不会被零长度的正则所分割,例如:

>>> re.split('x*', 'foo')

['foo']

>>> re.split("(?m)^$", "foo\n\nbar\n")

['foo\n\nbar\n']

re.findall(pattern, string[, flags])

以列表的形式返回string里匹配pattern的不重叠的子串。string会被从左到右依次扫描,返回的列表也是从左到右一次匹配到的。若是pattern里含有的话,那么会返回匹配到的组的列表;若是pattern里有多个组,那么各组会先组成一个元组,而后返回值将是一个元组的列表。

因为这个函数不会涉及到MatchObject之类的概念,因此,对新手来讲,应该是最好理解也最容易使用的一个函数了。下面就此来举几个简单的例子:

#简单的findall

>>> re.findall('\w+', 'hello, world!')

['hello', 'world']

#这个返回的就是元组的列表

>>> re.findall('(\d+)\.(\d+)\.(\d+)\.(\d+)', 'My IP is 192.168.0.2, and your is 192.168.0.3.')

[('192', '168', '0', '2'), ('192', '168', '0', '3')]

re. finditer(pattern, string[, flags])

和上面的findall()相似,但返回的是MatchObject的实例的迭代器。

仍是例子说明问题:

>>> for m in re.finditer('\w+', 'hello, world!'):

... print m.group()

...

hello

world

re.sub(pattern, repl, string[, count])

替换,将string里,匹配pattern的部分,用repl替换掉,最多替换count次(剩余的匹配将不作处理),而后返回替换后的字符串。若是string里没有能够匹配pattern的串,将被原封不动地返回。repl能够是一个字符串,也能够是一个函数(也能够参考我之前的例子)。若是repl是个字符串,则其中的反斜杆会被处理过,好比 \n 会被转成换行符,反斜杆加数字会被替换成相应的组,好比 \6 表示pattern匹配到的第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被匹配到的时候,都会被调用一次,传入一个匹配到的MatchObject对象,须要返回一个字符串,在匹配到的位置,就填入返回的字符串。

例子:

>>> def dashrepl(matchobj):

...     if matchobj.group(0) == '-': return ' '

...     else: return '-'

>>> re.sub('-{1,2}', dashrepl, 'pro----gram-files')

'pro--gram files'

零长度的匹配也会被替换,好比:

>>> re.sub('x*', '-', 'abcxxd')

'-a-b-c-d-'

特殊地,在替换字符串里,若是有\g这样的写法,将匹配正则的命名组(前面介绍过的,(?P...)这样定义出来的东西)。\g这样的写法,也是数字的组,也就是说,\g通常和\2是等效的,可是万一你要在\2后面紧接着写上字面意义的0,你就不能写成\20了(由于这表明第20个组),这时候必须写成\g0,另外,\g表明匹配到的整个子串。

例子:

>>> re.sub('-(\d+)-', '-\g<1>0\g<0>', 'a-11-b-22-c')

'a-110-11-b-220-22-c'

re.subn(pattern, repl, string[, count])

跟上面的sub()函数同样,只是它返回的是一个元组 (新字符串, 匹配到的次数)

,仍是用例子说话:

>>> re.subn('-(\d+)-', '-\g<1>0\g<0>', 'a-11-b-22-c')

('a-110-11-b-220-22-c', 2)

re.escape(string)

string中,除了字母和数字之外的字符,都加上反斜杆。

>>> print re.escape('abc123_@#$')

abc123\_\@\#\$

exception re.error

若是字符串不能被成功编译成正则表达式或者正则表达式在匹配过程当中出错了,都会抛出此异常。可是若是正则表达式没有匹配到任何文本,是不会抛出这个异常的。

正则对象

正则对象由re.compile()返回。它有以下的属性和方法。

match(string[, pos[, endpos]])

做用和模块的match()函数相似,区别就是后面两个参数。

pos是开始搜索的位置,默认为0。endpos是搜索的结束位置,若是endpospos还小的话,结果确定是空的。也就是说只有posendpos-1 位置的字符串将会被搜索。

例子:

>>> pattern = re.compile("o")

>>> pattern.match("dog")      # 开始位置不是o,因此不匹配

>>> pattern.match("dog", 1)   # 第二个字符是o,因此匹配

<_sre.SRE_Match object at ...>

search(string[, pos[, endpos]])

做用和模块的search()函数相似,posendpos参数和上面的match()函数相似。

split(string[, maxsplit=0])

findall(string[, pos[, endpos]])

finditer(string[, pos[, endpos]])

sub(repl, string[, count=0])

subn(repl, string[, count=0])

这几个函数,都和模块的相应函数一致。

flags

编译本RE时,指定的标志位,若是未指定任何标志位,则为0。

>>> pattern = re.compile("o", re.S|re.U)

>>> pattern.flags

48

groups

RE所含有的组的个数。

groupindex

一个字典,定义了命名组的名字和序号之间的关系。

例子:

这个正则有3个组,若是匹配到,第一个叫区号,最后一个叫分机号,中间的那个未命名

>>> pattern = re.compile("(?P<quhao>\d+)-(\d+)-(?P<fenjihao>\d+)")

>>> pattern.groups

3

>>> pattern.groupindex

{'fenjihao': 3, 'quhao': 1}

pattern

创建本RE的原始字符串,至关于源代码了,呵呵。

仍是上面这个正则,能够看到,会原样返回:

>>> print pattern.pattern

(?P<quhao>\d+)-(\d+)-(?P<fenjihao>\d+)

Match对象

re.MatchObject被用于布尔判断的时候,始终返回True,因此你用 if 语句来判断某个 match() 是否成功是安全的。

它有如下方法和属性:

expand(template)

template作为模板,将MatchObject展开,就像sub()里的行为同样,看例子:

>>> m = re.match('a=(\d+)', 'a=100')

>>> m.expand('above a is \g<1>')

'above a is 100'

>>> m.expand(r'above a is \1')

'above a is 100'

group([group1, ...])

返回一个或多个子组。若是参数为一个,就返回一个子串;若是参数有多个,就返回多个子串注册的元组。若是不传任何参数,效果和传入一个0同样,将返回整个匹配。若是某个groupN未匹配到,相应位置会返回None。若是某个groupN是负数或者大于group的总数,则会抛出IndexError异常。

>>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")

>>> m.group(0)       # 整个匹配

'Isaac Newton'

>>> m.group(1)       # 第一个子串

'Isaac'

>>> m.group(2)       # 第二个子串

'Newton'

>>> m.group(1, 2)    # 多个子串组成的元组

('Isaac', 'Newton')

若是有其中有用(?P...)这种语法命名过的子串的话,相应的groupN也能够是名字字符串。例如:

>>> m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds")

>>> m.group('first_name')

'Malcolm'

>>> m.group('last_name')

'Reynolds'

若是某个组被匹配到屡次,那么只有最后一次的数据,能够被提取到:

>>> m = re.match(r"(..)+", "a1b2c3")  # 匹配到3次

>>> m.group(1)                        # 返回的是最后一次

'c3'

groups([default])

返回一个由全部匹配到的子串组成的元组。default参数,用于给那些没有匹配到的组作默认值,它的默认值是None

例如:

>>> m = re.match(r"(\d+)\.(\d+)", "24.1632")

>>> m.groups()

('24', '1632')

default的做用:

>>> m = re.match(r"(\d+)\.?(\d+)?", "24")

>>> m.groups()      # 第二个默认是None

('24', None)

>>> m.groups('0')   # 如今默认是0了

('24', '0')

groupdict([default])

返回一个包含全部命名组的名字和子串的字典,default参数,用于给那些没有匹配到的组作默认值,它的默认值是None,例如:

>>> m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds")

>>> m.groupdict()

{'first_name': 'Malcolm', 'last_name': 'Reynolds'}

start([group])

end([group])

返回的是:被组group匹配到的子串在原字符串中的位置。若是不指定groupgroup指定为0,则表明整个匹配。若是group未匹配到,则返回 -1。

对于指定的m和g,m.group(g)和m.string[m.start(g):m.end(g)]等效。

注意:若是group匹配到空字符串,m.start(group)m.end(group)将相等。

例如:

>>> m = re.search('b(c?)', 'cba')

>>> m.start(0)

1

>>> m.end(0)

2

>>> m.start(1)

2

>>> m.end(1)

2

下面是一个把email地址里的“remove_this”去掉的例子:

>>> email = "tony@tiremove_thisger.net"

>>> m = re.search("remove_this", email)

>>> email[:m.start()] + email[m.end():]

'tony@tiger.net'

span([group])

返回一个元组: (m.start(group), m.end(group))

pos

就是传给RE对象的search()match()方法的参数pos,表明RE开始搜索字符串的位置。

endpos

就是传给RE对象的search()match()方法的参数endpos,表明RE搜索字符串的结束位置。

lastindex

最后一次匹配到的组的数字序号,若是没有匹配到,将获得None

例如:(a)b、((a)(b))和((ab))正则去匹配'ab'的话,获得的lastindex为1。而用(a)(b)去匹配'ab'的话,获得的lastindex为2。

lastgroup

最后一次匹配到的组的名字,若是没有匹配到或者最后的组没有名字,将获得None

re

获得本Match对象的正则表达式对象,也就是执行search()match()的对象。

string

传给search()match()的字符串。