1.正则表达式常见的具体应用场景如下:
-
手机号校验;
-
邮箱校验;
-
身份证校验;
-
网页标签匹配;
-
车牌号校验;
-
中文校验;
2.re模块
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式。re 模块使 Python 语言拥有全部的正则表达式功能。
1>元字符,量词,贪婪与非贪婪匹配,分组与或的使用
元字符:
字符 |
功能 |
. |
匹配任意1个字符(除了\n) |
[ ] |
匹配[ ]中列举的字符 |
\d |
匹配数字,即0-9 |
\D |
匹配非数字,即不是数字 |
\s |
匹配空白,即 空格 |
\S |
匹配非空白 |
\w |
匹配单词字符,即a-z、A-Z、0-9、_ |
\W |
匹配非单词字符 |
#案例演示01:(. 匹配任意1个字符(除了\n))
# . 匹配任意1个字符(除了\n)
import re
ret = re.match("t.o", "t\no")
if ret:
print(ret.group())
else:
print("匹配失败")
# . 匹配任意1个字符(除了\n)
import re
ret = re.match("t.o", "two")
if ret:
print(ret.group())
else:
print("匹配失败")
#案例演示02:([ ] 匹配[ ]中列举的字符 ,只匹配任意一个字符)
# [ ] 匹配[ ]中列举的字符 ,只匹配任意一个字符
import re
ret = re.match("t[1wqs]o", "two") # 将w换成9,查看匹配结果
if ret:
print(ret.group())
else:
print("匹配失败")
#案例演示03:(\d 匹配数字,即0-9)
# \d 匹配数字,即0-9
import re
ret = re.match("t\do", "t6o") # 将6换成a,查看匹配结果
if ret:
print(ret.group())
else:
print("匹配失败")
#案例演示04:(\D 匹配非数字,即不是数字)
# \D 匹配非数字,即不是数字
import re
ret = re.match("t\Do", "two") # 将w换成7,查看匹配结果
if ret:
print(ret.group())
else:
print("匹配失败")
#案例演示05:(\s 匹配空白,即 空格)
# \s 匹配空白,即 空格
import re
ret = re.match("t\so", "t o") # 将空格换成z,查看匹配结果
if ret:
print(ret.group())
else:
print("匹配失败")
#案例演示06:(\S 匹配非空白)
# \S 匹配非空白
import re
ret = re.match("t\So", "two") # 将w替换成空格,查看匹配结果
if ret:
print(ret.group())
else:
print("匹配失败")
#案例演示07:(\w 匹配单词字符,即a-z、A-Z、0-9、_)
# \w 匹配单词字符,即a-z、A-Z、0-9、_
import re
ret = re.match("t\wo", "t_o") # 将_分别替换成a、A、z、Z,分别查看匹配结果
if ret:
print(ret.group())
else:
print("匹配失败")
#案例演示08:(\W 匹配非单词字符)
# \W 匹配非单词字符
import re
ret = re.match("t\Wo", "t%o") # 将%分别替换成a、A、#、&,分别查看匹配结果
if ret:
print(ret.group())
else:
print("匹配失败")
量词:
字符 |
功能 |
* |
匹配前一个字符出现0次或者无限次,即可有可无 |
+ |
匹配前一个字符出现1次或者无限次,即至少有1次 |
? |
匹配前一个字符出现1次或者0次,即要么有1次,要么没有 |
{m} |
匹配前一个字符出现m次 |
{m,n} |
匹配前一个字符出现从m到n次 |
案例演示01:(* 匹配前一个字符出现0次或者无限次,即可有可无)
# * 匹配前一个字符出现0次或者无限次,即可有可无
import re
ret = re.match("tw*o","twwo") # 将ww分别替换成w、www、wwwwwwwww或者删除ww,分别查看匹配结果
if ret:
print(ret.group())
else:
print("匹配失败")
案例演示02:(+ 匹配前一个字符出现1次或者无限次,即至少有1次)
# + 匹配前一个字符出现1次或者无限次,即至少有1次
import re
ret = re.match("tw+o","twwo") # 将ww分别替换成w、www、wwwwwwwww或者删除ww,分别查看匹配结果,并比较与 *的区别
if ret:
print(ret.group())
else:
print("匹配失败")
案例演示03:(? 匹配前一个字符出现1次或者0次,即要么有1次,要么没有)
# ? 匹配前一个字符出现1次或者0次,即要么有1次,要么没有
import re
ret = re.match("tw?o","to")
if ret:
print(ret.group())
else:
print("匹配失败")
贪婪与非贪婪匹配:(?非贪婪匹配 +* 贪婪匹配)
案例演示04:({m} 匹配前一个字符出现m次)
# {m} 匹配前一个字符出现m次
import re
ret = re.match("tw{2}o", "twwo") # 将ww替换为www,查看匹配结果,比较区别
if ret:
print(ret.group())
else:
print("匹配失败")
案例演示05:({m,n} 匹配前一个字符出现从m到n次)
# {m,n} 匹配前一个字符出现从m到n次
import re
ret = re.match("tw{3,5}o","twwwwwo") # 将wwwww替换为ww,查看匹配结果
if ret:
print(ret.group())
else:
print("匹配失败")
# 特殊情况说明{3,},对应含义为:匹配前一字符至少出现三次的情况;
import re
ret = re.match("tw{3,}o","twwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwo")
if ret:
print(ret.group())
else:
print("匹配失败")
# 特殊情况说明{,5},对应含义为:匹配前一字符最多出现5次的情况;
import re
ret = re.match("tw{,5}o","twwwo")
if ret:
print(ret.group())
else:
print("匹配失败")
分组与或的使用:
匹配分组
字符 |
功能 |
| |
匹配左右任意一个表达式 |
(ab) |
将括号中字符作为一个分组 |
\num |
引用分组num匹配到的字符串 |
(?P<name>) |
分组起别名 |
(?P=name) |
引用别名为name分组匹配到的字符串 |
案例演示01:((ab) 将括号中字符作为一个分组)
# (ab) 将括号中字符作为一个分组 www.baidu.com
import re
ret = re.match("^(https://www)\.[a-z]+(\.com)$", "https://www.baidu.com")
if ret:
print(ret.group())
else:
print("匹配失败")
案例演示02:(| 匹配左右任意一个表达式)
# 定义邮箱列表
email_list = ["xiaoWang@163.com", "xiaoWang@163.comheihei", "12345678@qq.com"]
# 导包
import re
# 遍历列表,获取列表中的邮箱字符串
for email in email_list:
# 匹配每一个邮箱字符串,判断是否符合邮箱格式要求
ret = re.match("\w{4,20}@(163|qq|sina|139)(.com)$", email)
if ret:
print("正确邮箱:", ret.group())
else:
print("%s匹配失败" % email)
案例演示03:(\num 引用分组num匹配到的字符串)
# 匹配标签:<html>hh</html>
# \num 引用分组num匹配到的字符串 r 声明原生字符,特别针对\等
import re
ret = re.match(r"<([a-z]+)>[a-z]{2}</\1>","<html>hh</html>")
if ret:
print(ret.group())
else:
print("匹配失败")
案例演示04:((?P<name>) 分组起别名, (?P=name) 引用别名为name分组匹配到的字符串 )
# 匹配标签:<html><h1>hh</h1></html>
# (?P<name>) 分组起别名
# (?P=name) 引用别名为name分组匹配到的字符串
import re
ret = re.match(r"<(?P<xiaohei>[a-z]{4})><(?P<xiaobai>\w{2})>[a-z]{2}</(?P=xiaobai)></(?P=xiaohei)>","<html><h1>hh</h1></html>")
if ret:
print(ret.group())
else:
print("匹配失败")
匹配开头
现有王老师手机号:13051115888,要求使用正则表达式,判断该手机号是否合规?
思路分析:
-
手机号长度11位数字;
-
手机号以1开头;
-
手机号号段(3-8),例如:130、152、186,其中第二位为号段;
import re
ret = re.match("^1[3-8]\d{9}","13051115888")
if ret:
print(ret.group())
else:
print("匹配失败")
匹配结尾
现有赵老师邮箱号:zhaolaoshi123456@sina.com,要求使用正则表达式,判断该邮箱账号是否合规?
思路分析:
-
邮箱账号4-20位字符;
-
邮箱账号一般以.com结尾;
import re
ret = re.match("\w{4,20}@sina(.com)$","zhaolaoshi123456@sina.com") # 正则表达式中的(),代表分组匹配
if ret:
print(ret.group())
else:
print("匹配失败")
2>re.match函数(re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。 )
用法:re.match(pattern, string, flags=0)
函数参数说明:
参数 |
描述 |
pattern |
匹配的正则表达式 |
string |
要匹配的字符串。 |
flags |
标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 |
匹配成功re.match方法返回一个匹配的对象,否则返回None。
我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。
匹配对象方法 |
描述 |
group(num=0) |
匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。 |
groups() |
返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。 |
案例
# 导包
import re
# 使用re模块中的match(正则表达式,要匹配的字符串对象)方法进行匹配
ret = re.match("abc","abcdef")
if ret: # 判断匹配结果是否存在
print(ret.group())
else:
print("匹配失败")
3>re.search函数(re.search 扫描整个字符串并返回第一个成功的匹配。 )
用法:re.search(pattern, string, flags=0)
函数参数说明:
参数 |
描述 |
pattern |
匹配的正则表达式 |
string |
要匹配的字符串。 |
flags |
标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 |
匹配成功re.search方法返回一个匹配的对象,否则返回None。
我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。
匹配对象方法 |
描述 |
group(num=0) |
匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。 |
groups() |
返回一个包含所有小组字符串的元组,从 1 到 所含的小组号 |
案例1
import re
ret_01 = re.search('www', 'www.runoob.com') # 在起始位置匹配
if ret_01:
print(ret_01.group()) # 查看匹配到的对象
print(ret_01.span()) # 查看匹配到的对象的位置区间(下标索引)
else:
print("ret_01 匹配失败")
案例2
import re
ret_02 = re.search('com', 'www.runoob.com') # 不在起始位置匹配
if ret_02:
print(ret_02.group()) # 查看匹配到的对象
print(ret_02.span()) # 查看匹配到的对象的位置区间(下标索引)
else:
print("ret_02 匹配失败")
案例3
import re
# 字符串
line = "Cats are smarter than dogs";
# search匹配(分组)
searchObj = re.search( r'(.*) are (.*?) .*', line, re.M|re.I)
# 如果匹配结果存在,则分组查看匹配数据
if searchObj:
print "searchObj.group() : ", searchObj.group()
print "searchObj.group(1) : ", searchObj.group(1)
print "searchObj.group(2) : ", searchObj.group(2)
else:
print "Nothing found!!"
4>re.findall函数(在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。 )
注意: match 和 search 是匹配一次 findall 匹配所有。
用法:findall(string[, pos[, endpos]])
参数:
查找字符串中的所有数字,返回包含所有匹配结果的列表:
案例
import re
pattern = re.compile(r'\d+') # 查找数字
result1 = pattern.findall('runoob 123 google 456')
result2 = pattern.findall('run88oob123google456', 0, 10)
print(result1)
print(result2)
结果:
['123', '456']
['88', '12']
5>re.split函数(根据匹配进⾏切割字符串,并返回⼀个列表。)
用法:re.split(pattern, string, maxsplit=0, flags=0)
参数 |
描述 |
pattern |
匹配的正则表达式 |
string |
要匹配的字符串 |
maxsplit |
分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数 |
案例:
import re
ret = re.split(r":| ","dasdsa:asdadas:dasdadada")
print(ret)
6>re.sub函数(sub是substitute的所写,表示替换,将匹配到的数据进⾏替换。)
用法:re.sub(pattern, repl, string, count=0, flags=0)
#参数 描述
#pattern 必选,表示正则中的模式字符串
#repl 必选,就是replacement,要替换的字符串,也可为一个函数
#string 必选,被替换的那个string字符串
#count 可选参数,count 是要替换的最大次数,必须是非负整数。如果省略这个参数或设为 0,所有的匹配都会被替换
#flag 可选参数,标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等
import re
ret = re.sub(r"\d+", '998', "python = 997")
print(ret)
结果:
python=998
7>re.subn函数(行为与sub()
相同,但是返回一个元组 (字符串, 替换次数)
)
用法:re.subn(pattern, repl, string[, count])返回:(sub(repl, string[, count]), 替换次数)
import re
pattern = re.compile(r'(\w+) (\w+)')
s = 'i say, hello world!'
print(re.subn(pattern, r'\2 \1', s))
def func(m):
return m.group(1).title() + ' ' + m.group(2).title()
print(re.subn(pattern, func, s))
8>re.compile函数(compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。)
prog = re.compile(pattern)
result = prog.match(string)
等价于
result = re.match(pattern, string)
案例
>>>import re
>>> pattern = re.compile(r'\d+')
m = pattern.match('one12twothree34four', 3, 10) # 从'1'的位置开始匹配,正好匹配
>>> print m # 返回一个 Match 对象
<_sre.SRE_Match object at 0x10a42aac0>
>>> m.group(0) # 可省略 0
'12'
>>> m.start(0) # 可省略 0
3
>>> m.end(0) # 可省略 0
5
>>> m.span(0) # 可省略 0
(3, 5)
在上面,当匹配成功时返回一个 Match 对象,其中:
group([group1, …]) 方法用于获得一个或多个分组匹配的字符串,当要获得整个匹配的子串时,可直接使用 group() 或 group(0);
start([group]) 方法用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0;
end([group]) 方法用于获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引+1),参数默认值为 0;
span([group]) 方法返回 (start(group), end(group))