Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式。
re 模块使 Python 语言拥有全部的正则表达式功能。
compile 函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象。该对象拥有一系列方法用于正则表达式匹配和替换。
re 模块也提供了与这些方法功能完全一致的函数,这些函数使用一个模式字符串做为它们的第一个参数。
正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。在自动化测试中,也会经常应用到,当你想寻找某个值,它可能是与其他字符串拼接在一起的,这时候查找可能会找不到目标值,需要用到正则表达式对所获得的字符串进行切割或者匹配。
1、正则表达式代表的匹配字符
?: 匹配零次或一次前面的分组。
*: 匹配零次或多次前面的分组。
+: 匹配一次或多次前面的分组。
. 匹配所有字符,换行符除外。
^spam:匹配字符串开头,这里意味着字符串必须以 spam 开始。
spam$: 意味着字符串必须以 spam 结束。
{n}: 匹配 n 次前面的分组。n代表正整数。
{n,}: 匹配 n 次或更多前面的分组。
{,m}: 匹配零次到 m 次前面的分组。
{n,m}: 匹配至少 n 次、至多 m 次前面的分组。
{n,m}?或*?或+?: 对前面的分组进行非贪心匹配。
\d、\w 和\s: 分别匹配数字、单词和空格。
\D、\W 和\S: 分别匹配出数字、单词和空格外的所有字符。
[abc]: 匹配方括号内的任意字符(诸如 a、b 或 c)。
[^abc]: 匹配不在方括号内的任意字符。
2、正则表达式应用简单举例
3、compile(pattern, flags=0)[Regex对象]
re模块中包含一个重要函数是compile(pattern [, flags]) ,该函数根据包含的正则表达式的字符串创建模式对象Regex(即创建基本正则表达式规则,进行操作时直接引用该模式对象便可使用其中的规则),可以实现更有效率的匹配。
在直接使用字符串表示的正则表达式进行search,match和findall操作时,python会将字符串转换为正则表达式对象。而使用compile完成一次转换之后,在每次使用模式的时候就不用重复转换。
如,使用re.compile()函数进行转换后,re.search(pattern, string)的调用方式就转换为 pattern.search(string)的调用方式。
使用compile()函数
text="JGod is a handsome boy ,but he is a ider"
print re.findall(r'\w*o\w*',text) #查找有o的单词,r: 忽略所有的转义字符,打印出字符串中所有的倒斜杠
#输出结果为:['JGod', 'handsome', 'boy']
不使用compile()函数:
text="JGod is a handsome boy ,but he is a ider"
regex=re.compile(r'\w*o\w*')
print regex.findall(text)
#>>> ['JGod', 'handsome', 'boy']
3.1 pattern参数
pattern参数对应正则表达式规则。
3.2 flags参数
第二个参数flags是匹配模式,可以使用按位或’|’表示同时生效,也可以在正则表达式字符串中指定。
Pattern对象是不能直接实例化的,只能通过compile方法得到。匹配模式有:
1).re.I(re.IGNORECASE): 忽略大小写
2).re.M(re.MULTILINE): 多行模式,改变’^’和’$’的行为
3).re.S(re.DOTALL): 点任意匹配模式,改变’.’的行为
4).re.L(re.LOCALE): 使预定字符类 \w \W \b \B \s \S 取决于当前区域设定
5).re.U(re.UNICODE): 使预定字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性
6).re.X(re.VERBOSE): 详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释
4、re.match(pattern, string, flags)函数
第一个参数是正则表达式,如果匹配成功,则返回一个Match,否则返回一个None;
第二个参数表示要匹配的字符串;
第三个参数是标致位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。
例如:match(‘p’,’python’)返回值为真;match(‘p’,’www.python.org’)返回值为假。
# -*- coding:UTF-8 -*-
import re
line = "Cats are smarter than dogs"
# .* 表示任意匹配除换行符(\n、\r)之外的任何单个或多个字符
matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I)
if matchObj:
print ("matchObj.group() : ", matchObj.group())
print ("matchObj.group(1) : ", matchObj.group(1))
print ("matchObj.group(2) : ", matchObj.group(2))
else:
print ("No match!!")
>>matchObj.group() : Cats are smarter than dogs
>>matchObj.group(1) : Cats
>>matchObj.group(2) : smarter
5、re.search(pattern, string, flags=0)
e.search(pattern, string, flags)函数
search()的参数含义和match()是一样的。
re.search()会在给定字符串中寻找第一个匹配给定正则表达式的子字符串。如果找到了该模式, search() 方法将返回一个 Match 对象。Match 对象有一个 group() 方法,它返回被查找字符串中实际匹配的文本。
import re
# 因为正则表达式常常使用倒斜杠,向 re.compile()函数传入原始字符串就很方便
# r: 忽略所有的转义字符,打印出字符串中所有的倒斜杠
phoneNumber = re.compile(r'\d{3}-\d{3}-\d{3}') # Regex 对象
mo = phoneNumber.search('Mu Number is 020-000-666') # 返回一个 Match 对象
mo.group()
>> '020-000-666'
6、re.findall()
search() 将返回一个 Match 对象,包含被查找字符串中的第一次 匹配的文本,
而 findall() 方法将返回一组字符串,包含被查找字符串中的所有匹配,即以list形式返回所有匹配成功的结果。
7、贪心匹配和非贪心匹配
Python的正则表达式默认是 “贪心” 的,这表示在有二义的情况下,它们会尽可能匹配最长的字符串。花括号的 “非贪心” 版本匹配尽可能最短的字符串,即在结束的花括号后跟着一个问号。
注意: 问号在正则表达式中可能有两种含义: 声明非贪心匹配或表示可选的分组。这两种含义是完全无关的。
7.1 用加号匹配一次或多次
如果想要一个分组重复特定次数,就在正则表达式中该分组的后面,跟上花括号包围的数字。
格式:(targetString){startNo,endNo}
例如,正则表达式 (Ha){3} 将匹配字符串 ‘HaHaHa’,但不会匹配 ‘HaHa’, 因为后者只重复了 (Ha)分组两次。除了一个数字,还可以指定一个范围,即在花括号中写下一个最小值、一个逗号和 一个最大值。例如,正则表达式 (Ha){3,5} 将匹配’HaHaHa’、‘HaHaHaHa’和’HaHaHaHaHa’。也可以不写花括号中的第一个或第二个数字,不限定最小值或最大值。例如,(Ha){3,} 将匹配 3 次或更多次实例,(Ha){,5} 将匹配 0 到 5 次实例。花括号让正则表达式更简短。
greedyHaRegex = re.compile(r'(Ha){3,5}')
mo1 = greedyHaRegex.search('HaHaHaHaHa')
print(mo1.group())
nongreedyHaRegex = re.compile(r'(Ha){3,5}?')#非贪心匹配
mo2 = nongreedyHaRegex.search('HaHaHaHaHa')
print(mo2.group())
>> HaHaHaHaHa
>> HaHaHa
8、切割字符串split()方法(选中符合匹配外的字符)
import re
s="hello world"
print(s.split())#默认以空格进行切割,结果放在列表里面
print(s.split("o"))#以字符'o'为节点进行切割
print(s.count("o"))#统计字符'o'的个数
print(s.split("o")[0])#读取以字符’o’分隔的第一列数据
print(re.split('[/.o(]|\s+',s))#匹配方括号内的任意字符进行切割
执行结果如下:
['hello', 'world']
['hell', ' w', 'rld']
2
hell
['hell', '', 'w', 'rld']
应用实例:取页数
re.split('["共""页"]\s+',text)