正则表达式的常用元字符
\ 转义符,特殊含义的字符需要转义
^ 字符的启始(以什么开头)
$ 字符的结束 (以什么什么结尾)
* 匹配前面子表达式0次或多次
+ 匹配前面子表达式1次或多次
? 匹配前面子表达式0次或1次
{n,m} 配置至少n次 ,最多m次
. 匹配除 \n 之外的单个字符
(pattern) 匹配并获取这个匹配,例如匹配ab(cd)e 正则表达式只返回cd,() 外面的部分作为规则过滤,里面的被匹配的字符,打印出来。
[xyz] 字符集合,匹配任意集合里的字符 ,[a - z ] 表示匹配所有小写字符
[^xyz] 排除集合里的字符,不能匹配 ,[^a -z ]表示不匹配小写字符
\d 匹配一个数字,等价[0 - 9]
还有更多,可以去上网查
上面列举了一些正则表达式的匹配规则,在Python中如何应用。
import re
var = "aaabbbcccddd"
aaa = re.findall("ddd$",var)
print(aaa)
打印
>>>['ddd']
我们这个时候打印的是以ddd结尾的字符,如果ddd后面还有字符,就不能匹配了。
其他的都是类似的用法,匹配规则可以结合使用。
贪婪模式
import re
a ='<meta name=referrer content=always>测试<meta name=build content="2020-05-12 07:07:53">'
print(re.findall ("content=always>(.*)<",a))
打印
['测试<meta name=build content="2020-05-12 07:07:53">']
本例中,(.*)表示打印括号中被匹配的部分,我们想要匹配的是测试
两个字,但是后面还跟了一堆为什么呢,因为贪婪模式。.
表示匹配1个任意字符,*
表示匹配前面0或多次,两者加在一起就是匹配任意字符,虽然后面我们加了限制调价< 但是那一段字符串中,后面还有这个符号,同样也匹配到了就打印出来了。
非贪婪模式
import re
a ='<meta name=referrer content=always>测试<meta name=build content="2020-05-12 07:07:53">'
print(re.findall ("content=always>(.*?)<",a))
打印
['测试']
用上一个例子,我们只需要在匹配规则里面加入一个?
(匹配前面子表达式0次或1次)就可以了,这样就只会匹配第一个了。
sub替换模式
#语法格式
c = '<meta name=referrer content=always>测试<meta name=build content="2020-05-12 07:07:53">'
print(re.sub("(?<=content=always>).*?(?=<)",'test',a))
# ?<= 表示前面要匹配的内容
# .*? 被替换的内容
# ?= 表示后面要匹配的内容
# ?<= 和 ?= 适用 findall
打印
<meta name=referrer content=always>test<meta name=build content="2020-05-12 07:07:53"><meta name=referrer content=always>
做一下修改
c = '<meta name=referrer content=always>测试<meta name=build content="2020-05-12 07:07:53">'
print(re.sub("测试",'test',a))
这样修改之后,还是一样的效果,我们上面写那么多匹配规则,只是为了定位到测试
的位置。但是如果里面的内容不是测试,上面同样适用,下午的就匹配不到了,也就不能替换。
正则模块match与compile
预编译 - compile
预编译之后会把编译的内容当做一个对象,使用的时候不用重新编译,但是占用的空间会变多(空间换时间)
c = '<meta name=referrer content=always>测试<meta name=build content="2020-05-12 07:07:53">'
pattern = re.compile("(?<=content=always>).*?(?=<)")
print(pattern.findall(a))
print(pattern.sub('test',a))
打印
['测试']
<meta name=referrer content=always>test<meta name=build content="2020-05-12 07:07:53"><meta name=referrer content=always>
我们通过看这个例子的打印结果,就应该能够明白compile的作用了,就是把正则规则封装,然后可以复用,复用可以提高执行效率。
re.match()
只匹配一个,成功返回Match object, 失败返回None(匹配开头)
re.search()
只匹配一个,成功返回Match object, 失败返回None
re.findall()
查找所有匹配成功字符串,并返回list
re.finditer()
查找所有匹配字符串, 并返回iterator
re.fullmatch()
完全匹配string
例:
str = '<link rel="canonical" href="https://blog.csdn.net/chris_lele/article/details/58004771"/> ' \
'<link rel="canonical" href="https://blog.csdn.net/chris_lele/article/details/58004771"/> ' \
' <link rel="canonical" href="https://blog.csdn.net/chris_lele/article/details/58004771"/>'
print(re.search('<link',str))
print(re.findall('<link',str))
print(re.match('<link',str))
aaa = 'network'
print(re.fullmatch('network',aaa))
#运行结果
<re.Match object; span=(0, 5), match='<link'>
['<link', '<link', '<link']
<re.Match object; span=(0, 5), match='<link'>
<re.Match object; span=(0, 7), match='network'>
稍作更改,对比输出
str = '<alink rel="canonical" href="https://blog.csdn.net/chris_lele/article/details/58004771"/> ' \
'<link rel="canonical" href="https://blog.csdn.net/chris_lele/article/details/58004771"/> ' \
' <link rel="canonical" href="https://blog.csdn.net/chris_lele/article/details/58004771"/>'
print(re.search('<link',str))
print(re.findall('<link',str))
print(re.match('<link',str))
aaa = 'network'
print(re.fullmatch('net',aaa))
#打印结果
<re.Match object; span=(90, 95), match='<link'>
['<link', '<link']
None
None
group()
group()用来提出分组截获的字符串,()用来分组。
import re
a = "123abc456"
print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(0) #123abc456,返回整体
print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(1) #123
print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(2) #abc
print re.search("([0-9]*)([a-z]*)([0-9]*)",a).group(3) #456
适用与re.match
注意: 正则表达式不匹配换行符,当文本出现\n 换行符的时候,匹配规则就失效了,后面的就不匹配了。我们可以用sub先把换行符给替换掉在进行匹配。