re模块
re模块
re引擎由c编写
.元字符
一个.代表匹配一个任意字符(除了\n),下面代码表示2个字符在中间
import re
lis="gdnm tfnb xzxxlxxlzxzzcassfagkffdkgfkdkgkwsiil"
zx=re.findall("l..l",lis)
print(zx)
['lxxl']
^元字符
字符开头为标准,只匹配开头,如代码,当str开头为l满足^的条件,然后继续匹配其他条件
import re
lis="gdnm tfnb xzxxlxxlzxzzcassfagkffdkgfkdkgkwsiil"
lis="lgdlnm tfnb xzxxlxxlzxzzcassfagkffdkgfkdkgkwsiil"
zx=re.findall("^l..l",lis)
zx=re.findall("^l..l",lis)
print(zx)
['lgdl']
贪婪匹配:有多少匹配多少
$元字符
$匹配文本结束
*元字符
前一个字母的重复数量,0到无穷
+元字符
前一个字母的重复数量,1到无穷
import re
lis="asdfghjk"
lis2="asdfghjk"
zx=re.findall("jkl*",lis)
zx2=re.findall("jkl+",lis)
print(f"zx:{zx}")
print(f"zx2:{zx2}")
zx:['jk']
zx2:[]
因为+至少要有一个l,所以没找到,而*的话可以有0个l,所以匹配到了jk
?元字符
?的范围是0到1次
{}元字符
自定义范围
{0,+00}==*
{1,+00}==+
{0,1}==?
{6}==6
{0,}==*
惰性匹配
在元字符后面加上问号?即可,然后就会默认取最小的重复
import re
lis="asdfghjkkkkk"
zx=re.findall("jk*?",lis)
zx2=re.findall("jk+?",lis)
zx3=re.findall("jk{3}?",lis)
print(f"zx*?:{zx}")
print(f"zx+?:{zx2}")
print(f"zx{3}?:{zx3}")
zx*?:['j']
zx+?:['jk']
zx3?:['jkkk']
*最小为0所以没有k,+最小为1所以有一个k,而{3}只有3,最小就为3所以取3个k
[]元字符(字符集)
在[]里面只支持,-,^,其他符号视为字符
[]只取一个值,除非加了其他的元字符
import re
lis="asdjh546fghjkkkkkakkk"
zx=re.findall("a[a-z]",lis)
zx2=re.findall("a[a-z]*",lis)
zx3=re.findall("a[a-z]{2}",lis)
print(f"zx:{zx}")
print(f"zx2:{zx2}")
print(f"zx3:{zx3}")
zx:['as', 'ak']
zx2:['asdjh', 'akkk']
zx3:['asd', 'akk']
^符号在[]
^在[]中并不是,取首字符的意思,而是非的意思
import re
lis="asdjh546fghjka643kkkkakkk"
zx=re.findall("a[^a-z]",lis)
print(f"zx:{zx}")
zx:['a6']
元字符之转义符\
re转义
举两个例子
import re
zx=re.findall('\\\\d',"jbsvu9||\d")
print(zx)
print(len(zx[0]))
print('\d')
print('\\d')
['\d']
2
\d
\d
首先\d在python是没有意义的,这行代码在pycharm中首先被转义成\\d,然后给re引擎,re引擎在转义成\d,最终可以匹配到字符串中的\d,虽然拿到的是\\d,因为又被转义了
import re
zx=re.findall('\\\\f',"jbsvu9||\\f")
print(zx)
print(len(zx[0]))
print('\f')
print('\\f')
['\f']
2
这里是个符号....这里无法显示
\f
\f在python中有意义
|元字符
相当于或
import re
zx='k|kdlk|a'
print(re.findall('k|a',zx))
['k', 'k', 'k', 'a']
分组(search)
分组格式(?P
search只匹配第一个
import re
ll="zx100 sadk2 asjk12 asd12 zx323 zx23 damsl12"
r=re.search("(?P<name>[a-z]+)\d+",ll)
print(r)
print(r.group('name'))
<_sre.SRE_Match object; span=(0, 2), match='zx100'> 可以看到匹配的位置和字符
zx
那么怎么分两个组呢?
import re
ll="zx100 sadk2 asjk12 asd12 zx323 zx23 damsl12"
r=re.search("(?P<name>[a-z]+)(?P<age>\d+)",ll)
print(r)
print(r.group('name'))
print(r.group('age'))
()
把()里的看做一个整体,比如一个字母a
import re
l1="abcabcabcabcabcabclsd"
print(re.findall("(abc)+",l1))
print(re.findall("(?:abc)+",l1))
['abc']
['abcabcabcabcabcabc']
为啥会变成1这种情况,可以理解为括号的优先级高,会优先打印这个字符,所以通过?:去优先级
match
类似加了^的search,从头开始匹配第一个
import re
l1="45sdf1"
l2="sdfnj43"
print(re.match('\d+',l1))
print(re.match('\d+',l2))
<_sre.SRE_Match object; span=(0, 2), match='45'>
None
splite
re自己的splite与 python的有啥区别呢?
re的splite能用正则!
但是有坑
import re
l1="dakh jad sda|sad"
l2=" |das|dsa"
print(re.split('[ |]',l1))
print(re.split('[ |]',l2))
['dakh', 'jad', 'sda', 'sad']
['', '', 'das', 'dsa']
第一种结果很好理解
第二种为啥这样,说下流程
首先去字符串找“ “找到了,然后左边没有内容,于是他把字符分成两块,然后继续找,找到了|这个字符,然后这字符左边也是空,所以也把他分成了两块
sub
re的替换,第4个参数是替换的个数
import re
l1="zx213jlds534"
print(re.sub("\d","A",l1))
print(re.sub("\d","A",l1,3))
compile
import re
l1="fgk983nfd984"
com=re.compile("\d")
print(com.findall(l1))
相当于配置了匹配规则的re对象,可以提高编码效率
finditer
import re
l1="397053ubds9u2hrbfh98"
print(re.finditer("\d",l1))
<callable_iterator object at 0x000001D048001FD0>
返回一个迭代器对象,有啥好处呢,当数据很大的时候,可以使用迭代器拿数据一个一个取,但是迭代出来的还是对象,需要.grounp取值
finall实验
import re
l1="www.5463.com"
print(re.findall("www\.(5463)\.com",l1))
['5463']
会优先去找()里的
import re
l1="www.5463.com"
print(re.findall("www\.(?:5463)\.com",l1))
['www.5463.com']
加上?:可以去优先级