正则表达式(Regular Expression),又称为规则表达式。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。
re模块使python语言拥有全部的正则化功能,同时mre模块是用C语言写的,其匹配速度非常快。其中compile 函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象。该对象拥有一系列方法用于正则表达式匹配和替换。re 模块也提供了与这些方法功能完全一致的函数,这些函数使用一个模式字符串做为它们的第一个参数。
re.match(pattern,string,flags=0)
import re
str='Python is the best language in the world'
# match 只能匹配以xxx开头的子符串,第一个参数是正则,第二个参数是需要匹配的字符串
res=re.match('P',str)
res2=re.match('p',str,re.I) #有标识符:忽略大小写
res.group() # 匹配成功使用group方法取出字符串
res2.group()
print(res.group())
print(res2.group())
标志位flags
修饰符 | 描述 |
re.I (大写i) | 使匹配对大小写不敏感 |
re.L | 做本地化识别(locale-aware)匹配 |
re.M | 多行匹配,影响 ^ 和 $ |
re.S | 使 . 匹配包括换行在内的所有字符 |
re.U | 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B. |
re.X | 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。 |
使用 group(num) 和 groups( ) 匹配对象函数来获取匹配表达式
匹配对象方法 | 描述 |
group(num=0) | 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。 |
groups( ) | 返回一个包含所有小组字符串 的元组,从 1 到 所含的小组号。 |
str='Python is the best language in the world'
result=re.match('(.*) is (.*?) .*',str)
result.group()
print(result.group())
print(result.group(1))
print(result.group(2))
print(result.groups())
>>>
'<re.Match object; span=(0, 40), match='Python is the best language in the world'>'
'python is the best language in the world'
'python'
'the'
'('Python', 'the')'
常用的匹配规则------匹配字符
符号 | 匹配规则 |
.(点) | 匹配任意1个字符,除了换行符 \n。 |
[ abc ] | 匹配abc中的任意一个字符 |
\d | 匹配一个数字,即0-9 |
\D | 匹配非数字,即不是数字 |
\s | 匹配空白,即空格,tab键 |
\S | 匹配非空白,除空格,tab键之类的 |
\w | 匹配单词字符,即a-z、A-Z、0-9、_(下划线) |
\W | 匹配非单词字符,即符号@等 |
names='李达','小明','李华','小王' #相当于一个组
str1='Hello'
str2='23434jhdjh'
str3='s@jhfi233434'
str4=' named'
str5='sffd dff'
str6='dS3_3#@$^&'
str7='$#%d34_jfhu'
pattern='李.' # 匹配规则
pattern1='[eH]'
pattern2='\d\d\d'
pattern3='\D\D\D\D'
pattern4='\s\s'
pattern5='\S\S\S\S'
pattern6='\w\w\w\w\w'
pattern7='\W\W\W'
for name in names:
res = re.match(pattern,name)
if res:
print('匹配成功:%s'%res.group()) # 李达 李华
print(re.match(pattern1,str1).group()) # H
print(re.match(pattern2,str2).group()) # 234
print(re.match(pattern3,str3).group()) # S@JH
print(re.match(pattern4,str4).group()) # (两个空格)
print(re.match(pattern5,str5).group()) # sffd
print(re.match(pattern6,str6).group()) # dS3_3
print(re.match(pattern6,str6).group()) # $#%
常用的匹配规则-匹配字符数量
符号 | 匹配规则 |
* | 匹配前一个字符出现 0次或者无限次,即可有可无 |
+ | 匹配前一个字符出现 1次或者无限次,即 至少有1次 |
? | 匹配前一个字符出现 1次或者0次,即要么有1次,要么没有 |
{m} | 匹配前一个字符 出现m次 |
{m,} | 匹配前一个字符 至少出现m次 |
{n,m} | 匹配前一个字符 出现从n到m次 |
*:匹配前一个字符出现0次或者无限次,即可有可无
import re
ret1=re.match('[A-Z][A-Z]*','Mn')
ret.group()
>>> 'M'
ret2=re.match('[A-Z][a-z]*','Mn')
ret.group()
>>> 'Mn'
ret3=re.match('[A-Z][a-z]*','Mnsdfsdfs')
ret.group()
>>> 'Mnsdfsdfs'
+ :使用实例:写一个正则匹配python变量名【变量名的语法规则:不能以数字开头,变量名只能包含字母、数字、下划线】
re.match('[a-zA-Z_]+[\w]*',str) #开头是字母或者下划线(至少出现一次);后面可以有数字(单词字符),可有可无
result=re.match('[a-zA-Z_]+[\w]*','_name') # 可以完整匹配
print(result.group())
result=re.match('[a-zA-Z_]+[\w]*','na99me') # 可以完整匹配:数字可以在中间,数字不能开头
print(result.group())
result=re.match('[a-zA-Z_]+[\w]*','11name') # 报错:开头必须是字母或者下划线,不能是数字不可以匹配
print(result.group())
result=re.match('[a-zA-Z_]+','na99me') # 可以匹配,但不完整,不匹配数字,输出:na
print(result.group())
?:使用实例:匹配0-99的数字
result=re.match('[a-zA-Z]+[0-9]?','nad3a99me_e')
print(result.group()) # 输出:nad3
result=re.match('[a-zA-Z][0-9]?','na99me_e')
print(result.group()) # 输出:n
result=re.match('[a-zA-Z]+[0-9]?','namefusk99me_e')
print(result.group()) # 输出:namefusk9
{n,m} :匹配前一个字符出现从n到m次。使用实例:匹配qq邮箱,如XXXXXXXX@163.com
pattern='[a-zA-Z0-9]{6,11}@[0-9]{2,3}.com'
import re
mail=input('请输入你的邮箱:')
regexMail=re.match('[a-zA-Z0-9]{6,11}@163.com',mail)
if regexMail:
print('匹配成功,邮箱是{}'.format(regexMail.group()))
pass
常用的匹配规则-原生字符串
python字符串中 \ 作为转义字符开头,比如\n表示换行,\t表示tab键。为了表示\本身,再加一个\,成为 \\ 形式,在python中表示路径 ‘G:\py资料\1-上课资料\4-正则表达式课件\html’
mypath = 'G:\py资料\1-上课资料\4-正则表达式课件\html'
print(mypath) # 路劲输出异常
>>> G:\py资料-上课资料-正则表达式课件\html
mypath = 'G:\\py资料\\1-上课资料\\4-正则表达式课件\\html'
print(mypath) # 将\转义之后正常
>>> G:\py资料\1-上课资料\4-正则表达式课件\html
- re.match('c:\\\\a.txt','c:\\a.txt').group() # 正则中\也表示转义,所以要匹配字符串中的\需要再次转义
- 输出: 'c:\\a.txt’
- 正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"\",那么使用编程语言表示的正则表达式里将需要2个反斜杠"\"。
- 在python中有原生字符串 \,在字符串前面加上r表示字符串中的\不转义。
re.match(r'c:\\a.txt','c:\\a.txt').group() # 在正则前加r,表示原生字符串,python字符串不转义。
输出: 'c:\\a.txt’
常用的匹配规则-匹配开头结尾
符号 | 匹配规则 |
^ | 一:匹配字符串开头 二:否定,取反的意思 |
$ | 匹配字符串结尾 |
# 通过^限定开头字符串
result=re.match('^P.*','Python is language')
if result:
print(result.group()) #输出Python is language
pass
# 通过$来限定结尾
# 当输入不正确地址的邮箱时,如果没有结尾限定,仍然会输出结果
ret = re.match('[\w]{4,20}@163\.com','python@163.comsdsdds')
ret.group()
>>>'python@163.com'
# 通过$来限定结尾,只有符合格式才会顺利输出
mile=input('请输入你的邮箱:')
result=re.match('[\w]{6,11}@[\w]{2,3}.com$',mile)
if result:
print(result.group())
常用的匹配规则- 分组匹配
符号 | 匹配规则 |
| | 匹配左右任意一个表达式 |
(ab) | 将括号中字符作为一个分组 |
\num | 引用 第num个分组,将其匹配到的字符串 |
(?P<name>规则符号) | 分组起别名 |
(?P=name) | 引用别名为name分组匹配到的字符串 |
|:匹配出0-100之间的数字
ret=re.match('[1-9]?\d$|100','78')
ret.group()
>>> '78'
ret= re.match('[1-9]?\d$|100','100')
ret.group()
>>> '100'
(ab) 分组使用:分别匹配电号码区号和电话号码,将其分为两个组
re.match('([0-9]*)-(\d*)','0912-374658465').group()
>>> '0912-374658465'
re.match('([0-9]*)-(\d*)','0912-374658465').group(1)
>>> '0912'
re.match('([0-9]*)-(\d*)','0912-374658465').group(2)
>>> '374658465'
\num 的使用 :匹配html中的文本
data='<div><h1>www.baidu.com</h1></div>'
re.match(r'<([a-zA-Z]+)><([a-zA-Z0-9]+)>(.+)</\2></\1>',data).group() #'<div><h1>www.baidu.com</h1></div>'
re.match(r'<([a-zA-Z]+)><([a-zA-Z0-9]+)>(.+)</\2></\1>',data).group(1) #'div'
re.match(r'<([a-zA-Z]+)><([a-zA-Z0-9]+)>(.+)</\2></\1>',data).group(2) #'h1'
re.match(r'<([a-zA-Z]+)><([a-zA-Z0-9]+)>(.+)</\2></\1>',data).group(3) #'www.baidu.com'
常用的匹配规则- 分组匹配
ret=re.match(r'<(\w*)><(\w*)>.*</\2></\1>','<div><h1>www.baidu.com</h1></div>')
print(ret.group()) # \1 表示引用前面第一组
>>> '<div><h1>www.baidu.com</h1></div>'
使用组引用的时候如果有多个组就容易造成混乱,比如下面多个组引用,这样很混乱也不容易阅读。解决这个问题得给分组起别名
- (?P<name>) 取别名
- (?P=name) 引用字符串
ret=re.match(r'<(?P<name1>\w*)><(?P<name2>\w*)>.*</(?P=name2)></(?P=name1)>','<div><h1>www.baidu.com</h1></div>')
print(ret.group())
>>> '<div><h1>www.baidu.com</h1></div>'
re.compile(pattern)
- reg=re.compile(pattern) #将一个字符串编译成字节码(正则化表达式对象)
- result=reg.match(string)
- 使用 re.compile( ) 和保存所产生的正则表达式对象重用效率更高,只需要转换一次
re.search(pattern,string,flags=0)
search在全文中匹配一次,匹配到就返回。示例:扫描字符串,寻找的第一个由该正则表达式模式产生匹配的位置,并返回相应的MatchObject实例。
import re
re.search('bc','abcdgrgbc') # 在整个字符串中匹配,匹配到第一个就返回
>>> <_sre.SRE_Match object; span=(1,3), match='bc'>
re.search('bc','abcdgrgbc').group()
>>> 'bc'
re.findall(string[,pos[,endpos]])
- 匹配所有返回一个列表,这个方法使用频率较高。
- 查询字符串中某个正则表达式全部的非重复出现的内容,返回的是一个符合正则化表达式的结果。
- 可选参数pos:指定字符串的起始位置,默认为 0。 可选参数endpos:指定字符串的结束位置,默认为字符串的长度。
data='华为是华人的骄傲华侨'
res=re.findall('华.',data)
print(res) # 匹配所有满足正则化表达式的对象,以列表方式输出
# 输出:['华为', '华人', '华侨']
Res=re.search('华.',data)
print(Res)
print(Res.group()) # 只要匹配到正则化表达式就输出,只输出一个
reg=re.compile('华.') #创建一次正则对象转换,后续不需要转换,直接查找
print(reg.search(data).group())
print(reg.findall(data))
re.sub(pattern,repl,string,count=0,flags=0)
实现目标的搜索、替换。将匹配到的数据进行替换,将string中的pattern替换成repl,count为匹配后替换的最大次数,0表示替换所有的匹配。
datas='Python是很受欢迎的编程语言'
pattern='[a-zA-Z]+'
res=re.sub(pattern,'java',datas)
print(res) # 替换成功
re.subn(pattern,repl,string,count=0,flags=0)
完成目标的搜索、替换,并且返回被替换的数量。
datas='Python是很受欢迎的编程语言,Python'
pattern='[a-zA-Z]+'
resn=re.subn(pattern,'java',datas)
print(resn) # 以元组形式:返回替换成功的内容,并且返回替换次数
# 返回: ('java是很受欢迎的编程语言,java', 2)
re.split(pattern,string,maxsplit=0,flags=0)
根据匹配pattern进行切割字符串string,并返回一个列表。maxsplit是分割次数,1表示分隔1次,0表示不限制次数。
# 以,逗号切割字符串,并且最多两次
ret=re.split(',','hello,world,hello,world',2)
ret
['hello', 'world', 'hello,world']
贪婪模式和非贪婪模式
贪婪模式:在满足条件的情况下,尽可能多的匹配数据
非贪婪模式:在满足条件的情况下,尽可能少的匹配数据
在正则化表达式中加入 ? 就将贪婪模式 转化为 非贪婪模式(只要匹配到一个就停止)
import re
rs=re.match('\d{6,9}','76544446788') #贪婪模式
print(rs.group()) #输出:765444467 9位
rs=re.match('\d{6,9}?','76544446788') #非贪婪模式
print(rs.group()) #输出:765444 6位
content='ajhdafdjfk'
res=re.compile('a.*d')
result=res.match(content)
print('贪婪模式:{}'.format(result.group())) #输出:贪婪模式:ajhdafd
res2=re.compile('a.*?d')
result2=res2.match(content)
print('非贪婪模式:{}'.format(result2.group())) #输出:非贪婪模式:ajhd
案例:匹配网站图片URL地址
图片url:<img src=" //gtd.alicdn.com/sns_logo/i1/TB124_3NXXXXXasXVXXSutbFXXX.jpg_240x240xz.jpg">正则表达式应该写成'<img src="(.*")>'非贪婪模式:'<img src="(.*?)">'
默认贪婪模式:
使用非贪婪模式: '<img scr="(.*?)"'