1. 正则表达式基础

1.1. 简单介绍

正则表达式并不是Python的一部分。正则表达式是用于处理字符串的强大工具,拥有自己独特的语法以及一个独立的处理引擎,效率上可能不如str自带的方法,但功能十分强大。得益于这一点,在提供了正则表达式的语言里,正则表达式的语法都是一样的,区别只在于不同的编程语言实现支持的语法数量不同;但不用担心,不被支持的语法通常是不常用的部分。如果已经在其他语言里使用过正则表达式,只需要简单看一看就可以上手了。

下图展示了使用正则表达式进行匹配的流程: 

 day18-python的正则表达式_字符串



正则表达式的大致匹配过程是:依次拿出表达式和文本中的字符比较,如果每一个字符都能匹配,则匹配成功;一旦有匹配不成功的字符则匹配失败。如果表达式中有量词或边界,这个过程会稍微有一些不同,但也是很好理解的,看下图中的示例以及自己多使用几次就能明白。


下图列出了Python支持的正则表达式元字符和语法:   

 day18-python的正则表达式_正则_02


1.2. 数量词的贪婪模式与非贪婪模式

正则表达式通常用于在文本中查找匹配的字符串。Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;非贪婪的则相反,总是尝试匹配尽可能少的字符。例如:正则表达式"ab*"如果用于查找"abbbc",将找到"abbb"。而如果使用非贪婪的数量词"ab*?",将找到"a"。

1.3. 反斜杠的困扰

与大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"\",那么使用编程语言表示的正则表达式里将需要4个反斜杠"\\\\":前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r"\\"表示。同样,匹配一个数字的"\\d"可以写成r"\d"。有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。

r表示raw的简及raw string 意思是原生字符,也就是说是这个字符串中间的特殊字符不用转义

比如你要表示‘\n’,可以这样:r'\n'

但是如果你不用原生字符 而是用字符串你得这样:‘\\n’


2.re模块

re模块是python中处理正则表达式的一个模块,通过re模块的方法,把正则表达式pattern编译成正则对象,以便使用正则对象的方法。那为什么要使用re模块来把正则表达式搞成正则对象呢,最主要的是可以提高代码的执行效率,我们来看个例子:

import timeit

print timeit.timeit(setup='''import re; reg = re.compile('<(?P<tagname>\w*)>.*</(?P=tagname)>')''', stmt='''reg.match('<h1>xxx</h1>')''', number=1000000)

print timeit.timeit(setup='''import re''', stmt='''re.match('<(?P<tagname>\w*)>.*</(?P=tagname)>', '<h1>xxx</h1>')''', number=1000000)

结果:

0.504413156462

1.20703154234

解释:timeit.timeit是用来统计程序执行的时间的,和明显第一个print的执行时间要比第二个的执行时间快好多,这个就是把正则表达是表示成正则对象最明显的好处。下面我们就可以看看如何把正则表达式转换成正则对象


1 re.compile(pattern[, flags])

这个方法是就是将字符串的正则表达式编译城正则对象,第二个参数flag是匹配模式,取值可以使用按位或者运算符“|”表示同时生效,比如:re.I | re.M,flag的可选值有:

re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)

M(MULTILINE): 多行模式,改变'^'和'$'的行为

S(DOTALL): 点任意匹配模式,改变'.'的行为

L(LOCALE): 使预定字符类 \w \W \b \B \s \S 取决于当前区域设定

U(UNICODE): 使预定字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性

X(VERBOSE): 详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释。以下两个正则表达式是等价的:


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

\. # the decimal point

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

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



2正则对象的方法


2.1match方法和search方法


#正则对象的match匹配
#match(string[, pos[, endpos]])
#
# string:匹配使用的文本,
#
# pos: 文本中正则表达式开始搜索的索引。及开始搜索string的下标
#
# endpos: 文本中正则表达式结束搜索的索引。
#
# 如果不指定pos,默认是从开头开始匹配,如果匹配不到,直接返回None
import re
reg = re.compile(r'\w*(hello w.*)(hello c.*)')
a = 'hello world hello caicai'
result = reg.match(a)
print(result)
print(result.groups())

b = 'aa' + a
print(b)
result2 = reg.match(b)
print(result2)
print(result2.groups())

#正则对象的search方法做一个比较,全局搜
search(string[, pos[, endpos]])

# 这个方法用于查找字符串中可以匹配成功的子串。从string的pos下标处起尝试匹配pattern,
# 如果pattern结束时仍可匹配,则返回一个Match对象;若无法匹配,则将pos加1后重新尝试匹配;
# 直到pos=endpos时仍无法匹配则返回None。下面看个列子:

result3 = reg.search(b)
print('##'*30)
print(result3)
print(result3.groups())

输出结果
<_sre.SRE_Match object at 0x0000000002D220B8>
('hello world ', 'hello caicai')
aahello world hello caicai
<_sre.SRE_Match object at 0x0000000002D22140>
('hello world ', 'hello caicai')
############################################################
<_sre.SRE_Match object at 0x0000000002D221C8>
('hello world ', 'hello caicai')