同样的概念也适用于正则表达式— 在模式匹配发生之前,正则表达式模式必须编译 成正则表达式对象。由于正则表达式在执行过程中将进行多次比较操作,因此强烈建议使 用预编译。而且,既然正则表达式的编译是必需的,那么使用预编译来提升执行性能无疑 是明智之举。re.compile()能够提供此功能。
一、使用 compile()函数编译正则表达式
compile(pattern, flags=0)
Compile a regular expression pattern, returning a pattern object.
从compile()函数的定义中,可以看出返回的是一个匹配对象,它单独使用就没有任何意义,需要和findall(), search(), match()搭配使用。
def main():
content = 'Hello, I am Jerry, from Chongqing, a montain city, nice to meet you……'
regex = re.compile('\w*o\w*')
x = regex.findall(content)
y = regex.match(content)
z = regex.search(content)
二、匹配对象以及 group()和 groups()方法
group()要么返回整个匹配对象,要么根据要求返回特定子组。groups()则仅返回一个包含 唯一或者全部子组的元组。
三、使用 match()方法匹配字符串
match()是将要介绍的第一个 re 模块函数和正则表达式对象(regex object)方法。match()函数试图从字符串的起始部分对模式进行匹配。如果匹配成功,就返回一个匹配对象;如果 匹配失败,就返回 None,匹配对象的 group()方法能够用于显示那个成功的匹配。
>>> m = re.match('foo', 'foo') # 模式匹配字符串
>>> if m is not None: # 如果匹配成功,就输出匹配内容
... m.group()
...
'foo'
四、使用 search()在一个字符串中查找模式(搜索与匹配的对比)
search()的工作方式与 match()完全一致,不 同之处在于 search()会用它的字符串参数,在任意位置对给定正则表达式模式搜索第一次出现 的匹配情况。如果搜索到成功的匹配,就会返回一个匹配对象;否则,返回 None。
>>> m = re.search('foo', 'seafood') # 使用 search() 代替
>>> if m is not None: m.group()
...
'foo'
五、重复、特殊字符以及分组
正则表达式中最常见的情况包括特殊字符的使用、正则表达式模式的重复出现,以及使用 圆括号对匹配模式的各部分进行分组和提取操作。曾看到过一个关于简单电子邮件地址的 正则表达式(\w+@\w+\.com)。
为了表示主机名是可选的,需要创建一个模式来匹配主机名(后面跟 着一个句点),使用“?”操作符来表示该模式出现零次或者一次,然后按照如下所示的方式, 插入可选的正则表达式到之前的正则表达式中:\w+@(\w+\.)?\w+\.com。
使用圆括号来匹配和保存子组,以便于后续处理,而不是确定一个正则表达 式匹配之后,在一个单独的子程序里面手动编码来解析字符串。
>>> m = re.match('(\w\w\w)-(\d\d\d)', 'abc-123')
>>> m.group() #完整匹配
'abc-123'
>>> m.group(1) #子组1
'abc'
>>> m.group(2) #子组2
'123'
>>> m.groups() #全部子组
('abc', '123')
六、使用 findall()和 finditer()查找每一次出现的位置
findall()查询字符串中某个正则表达式模式全部的非重复出现情况。findall()总是返回一个列表,如果 findall()没有找到匹配的部分,就返回一个空列表,但如果匹配成功,列表将包含所有成 功的匹配部分(从左向右按出现顺序排列)。
子组在一个更复杂的返回列表中搜索结果,而且这样做是有意义的,因为子组是允许从单个正则表达式中抽取特定模式的一种机制。对于一个成功的匹配,每个子组匹配是由 findall()返回的结果列表中的单一元素;对于多个成功的匹配,每个子组匹配是返回的一个元组中的单一元素,而且每个元组(每个元组下·都对应一个成功的匹配)是结果列表中的元素。
七、使用 sub()和 subn()搜索与替换
有两个函数/方法用于实现搜索和替换功能: sub()和 subn()。subn()和 sub()一样,但 subn()还返回一个表示替换的总数,替换后的字符串和表示替换总数的数字一起作为一个拥有两个元素的元组返回。
格式为re.sub(pattern, repl, string, count=0, flags=0)
例子如下
>>> re.sub('X', 'Mr. Smith', 'attn: X\n\nDear X,\n')
'attn: Mr. Smith\012\012Dear Mr. Smith,\012'
八、在限定模式上使用 split()分隔字符串
如果给定分隔符不是使用特殊符号来匹配多重模式的正则表达式,那么 re.split()与str.split()的工作方式相同
>>> re.split(':', 'str1:str2:str3')
['str1', 'str2', 'str3']
另外一个例子
>>> import re
>>> DATA = (
... 'Mountain View, CA 94040',
... 'Sunnyvale, CA',
... 'Los Altos, 94023',
... 'Cupertino 95014',
... 'Palo Alto CA',
... )
>>> for datum in DATA:
... print re.split(', |(?= (?:\d{5}|[A-Z]{2})) ', datum)
...
['Mountain View', 'CA', '94040']
['Sunnyvale', 'CA']
['Los Altos', '94023']
['Cupertino', '95014']
['Palo Alto', 'CA']