Python中常用的正则表达式

正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。(非python独有,但是python的re模块提供了实现,在python中写正则表达式几乎都用这个库)
样例展示:
这里要用到在线正则表达式测试
在这里插入图片描述
右侧是常用的正则表达式,可以从待匹配的文本中匹配到相应的结果。
使用方法:
常用的匹配规则☆☆☆☆☆
在这里插入图片描述
后面会详细讲解一些常见规则的用法。

re.match

re.match尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就会返回none。

最常规的匹配

re.match(pattern,string.flags=0)

这个函数有三个参数,第一个就是你所写的正则表达式,第二个是所要匹配的目标字符串,第三个是一个匹配模式。

import re

content='Hello 123 4567 World_This is s Regex Demo'
print(len(content))#要匹配的内容的长度
result=re.match('^Hello\s\d\d\d\s\d{4}\s\w{10}.*Demo$',content)
#^、$分别代表匹配一行字符串的开头和结尾,\s:任意空白字符,\d:任意数字,{n}:匹配n个前面(此处为数字)的表达式
# \w匹配字母、数字或下划线 .(点号)匹配任意字符
print(result)
print(result.group())#返回匹配结果
print(result.span())#匹配结果的范围

运行结果
在这里插入图片描述

泛匹配

import re

content='Hello 123 4567 World_This is s Regex Demo'
result=re.match('^Hello.*Demo$',content)
#.*可以匹配中间的所有字符
print(result)
print(result.group())#返回匹配结果
print(result.span())#匹配结果的范围

在这里插入图片描述
运行结果,和上面是一样的。所以“.*”是经常使用的方式,因为比较方便。

匹配目标

import re

content='Hello 123 4567 World_This is s Regex Demo'
result=re.match('^Hello\s(\d+)\s.*Demo$',content)
#把需要匹配的目标用()括起来,然后指定左右端点,此处是两个空格\s
print(result)
print(result.group(1))#返回匹配结果,也就是第一个()其中的内容:123
print(result.span())#匹配结果的范围

在这里插入图片描述

贪婪匹配

import re

content='Hello 1234567 World_This is s Regex Demo'

result=re.match('^He.*(\d+).*Demo$',content)
#贪婪匹配,会把最后一个数字匹配到括号里
print(result)
print(result.group(1))#返回匹配结果

“.*”的匹配方式就是竟可能匹配更多的字符(把最后一个数字之前的所有数字都匹配进去了)
在这里插入图片描述

非贪婪匹配

与贪婪匹配对应,重点在一个问号的区别。
“我好疑惑,我吃太多好像不太好,我尽可能少吃一点儿吧~!”

import re

content='Hello 1234567 World_This is s Regex Demo'

result=re.match('^He.*?(\d+).*Demo$',content)
#非贪婪匹配,尽可能匹配更少的字符,一遇到数字马上停止,转而把数字匹配到括号中去
print(result)
print(result.group(1))#返回匹配结果

在这里插入图片描述

匹配模式

先看一下这个例子(文本中有换行符):

import re

content='''Hello 1234567 World_This
is s Regex Demo
'''

result=re.match('^He.*?(\d+).*?Demo$',content)
print(result)

在这里插入图片描述
从运行结果中可以看到没有匹配成功,因为.(点号)只能匹配换行符以外的任意字符。
改进以下,加入第三个参数:匹配模式

扫描二维码关注公众号,回复: 3887469 查看本文章
import re

content='''Hello 1234567 World_This
is a Regex Demo
'''

result=re.match('^He.*?(\d+).*?Demo$',content,re.S)#re.S使.匹配换行符在内的所有字符
print(result)
print(result.group(1))#返回匹配结果

在这里插入图片描述
加入匹配模式之后,可以成功匹配了。
另外还有一些修饰符,在需要的时候也可以使用,如下图:
在这里插入图片描述

转义

如果待匹配的文本中含有特殊字符(如$),那么直接在match中写入包括这个特殊字符在内的表达式是不行的:

import re

content='price is $5.00'
result=re.match('price is $5.00',content)
print(result)

在这里插入图片描述

解决:在特殊字符前加反斜杠:“\”。如下:

result=re.match('price is \$5\.00',content)

在这里插入图片描述

总结

尽量使用泛匹配、使用括号得到匹配目标、尽量使用非贪婪模式、有换行符就用re.S。

re.search

前面提到过, match ()方法是从字符串的开头开始匹配的,一旦开头不匹配,那么整个匹配就失败了 ,因此match()方法有比较大的限制。
re.search会扫描整个字符串,并且返回第一个成功的匹配,而不管开头是不是一样的。

import re

content="Extra stings Hello 1234567 World_Thisis a Regex Demo Extra stings"


result=re.search('Hello.*?(\d+).*?Demo',content)

print(result)
print(result.group(1))#返回匹配结果

在这里插入图片描述
总结:为了匹配方便,能用search就不用match

匹配练习

下面是一段html代码,里面是一些歌的列表。我们想要获取active标签下的歌名和歌手信息。我们用re.search()方法来匹配。

import re


html = '''<div id="songs-list">
<h2 class="title">经典老歌</h2>
<p class="introduction">
    经典老歌列表
</p>
<ul id="list"class="list-group">
    <li data-view="2">一路上有你</li>
    <li data-view="7">
        <a href="/2.mp3"singer="任贤齐">沧海一声笑</a>
    </li>
    <li data-view="4"class="active">
        <a href="/3.mp3"singer="齐秦">往事随风</a>
    </li>
    <li data-view="6"><a href="/4.mp3"singer="begoud">光辉岁月</a></li>
    <li data-view="5"><a href="/5.mp3"singer="陈慧琳">记事本</a></li>
    <li data-view="5">
        <a href="/6.mp3"singer="邓丽君"><li class="fa fa-user">但愿人长久</a>
    </li>
</ul>
</div>'''

result=re.search('<li.*?active.*?singer="(.*?)">(.*?)</a>',html,re.S)
if result:
    print(result.group(1),result.group(2))

在这里插入图片描述
非常成功地提取出来了。
在上面的基础上,尝试匹配第二个标签,那么把匹配字段中的active去掉就可以了,这样第一次匹配到的就是第二个标签中的内容了:

result=re.search('<li.*?singer="(.*?)">(.*?)</a>',html,re.S)

在这里插入图片描述
如果把re.S去掉会匹配到什么结果呢?试试看:

result=re.search('<li.*?singer="(.*?)">(.*?)</a>',html)

在这里插入图片描述
从运行结果可以看到,直接匹配到了第四个标签中的内容。
这是因为不加re.S的话,表达式中的点号是不能匹配换行符的,而前几个标签,在起始的“li”与结束的“”直接都存在的换行符,因此无法被匹配到。

re.findall

搜索字符串,以列表形式返回全部能匹配的子串。

import re


html = '''<div id="songs-list">
<h2 class="title">经典老歌</h2>
<p class="introduction">
    经典老歌列表
</p>
<ul id="list"class="list-group">
    <li data-view="2">一路上有你</li>
    <li data-view="7">
        <a href="/2.mp3"singer="任贤齐">沧海一声笑</a>
    </li>
    <li data-view="4"class="active">
        <a href="/3.mp3"singer="齐秦">往事随风</a>
    </li>
    <li data-view="6"><a href="/4.mp3"singer="begoud">光辉岁月</a></li>
    <li data-view="5"><a href="/5.mp3"singer="陈慧琳">记事本</a></li>
    <li data-view="5">
        <a href="/6.mp3"singer="邓丽君">但愿人长久</a>
    </li>
</ul>
</div>'''


results=re.findall('<li.*?href="(.*?)".*?singer="(.*?)">(.*?)</a>',html,re.S)
#href表示超链接
#findall的返回值是按()中所标识的字段来匹配的。比如这条语句中就有三个()。
print(results)
print(type(results))#看一下结果的类型
for result in results:#循环打印出列表中的每一个元素
    print(result)
    print(result[0],result[1],result[2])#列表中每一个元素都是一个元组,一个元组里面有三个元素

在这里插入图片描述
上图中,匹配到了所有需要的信息:超链接,歌手,歌曲名。
但是可以发现,第一个标签中的没有被匹配到,因为它没有带超链接。
我们再改改,以便匹配到所有的标签:

results=re.findall('<li.*?>\s*?(<a.*?>)?(\w+)(</a>)?\s*?</li>',html,re.S)
#前后两个li标志一个标签的开始和结束
#\s*?用来匹配可能出现的空白字符
print(results)
#print(type(results))#看一下结果的类型
for result in results:#循环打印出列表中的每一个元素
    print(result[1])

在这里插入图片描述
可见,所有的标签都被匹配到了。

re.sub

替换字符串中每一个匹配的子串后返回替换后的字符串。
第一个参数是表达式,第二个参数为替换成什么字符串(可以为空),第三个参数是原字符串。

import re


content='Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'
content=re.sub('\d+','',content)
print(content)

在这里插入图片描述
如上图,我们将原字符串中的数字替换为空格。
下面是替换为指定的字符串的例子:

import re

content='Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'
content=re.sub('\d+','Replacement',content)
print(content)

在这里插入图片描述
再看看,假如我们要替换成的内容,又包含了原来的内容,怎么处理呢?

import re

content='Extra stings Hello 1234567 World_This is a Regex Demo Extra stings'
content=re.sub('(\d+)',r'\1 8910',content)
#\1表示第一个括号中的内容,前面加r表示\不会被转义
print(content)

\1就可以将括号中匹配到的内容再拿来用了。
在这里插入图片描述

再回到上面那个歌曲列表的例子,想获取所以li节点的歌名,直接用正则表达式来提取可能会比较麻烦。我们可以先用sub方法把里面的标签都替换为空,再用findall方法就可以很方便地提取了:

import re

html = '''<div id="songs-list">
<h2 class="title">经典老歌</h2>
<p class="introduction">
    经典老歌列表
</p>
<ul id="list"class="list-group">
    <li data-view="2">一路上有你</li>
    <li data-view="7">
        <a href="/2.mp3"singer="任贤齐">沧海一声笑</a>
    </li>
    <li data-view="4"class="active">
        <a href="/3.mp3"singer="齐秦">往事随风</a>
    </li>
    <li data-view="6"><a href="/4.mp3"singer="begoud">光辉岁月</a></li>
    <li data-view="5"><a href="/5.mp3"singer="陈慧琳">记事本</a></li>
    <li data-view="5">
        <a href="/6.mp3"singer="邓丽君">但愿人长久</a>
    </li>
</ul>
</div>'''

html=re.sub('<a.*?>|</a>','',html)
#把两种形式的a标签替换为空
print(html)
results=re.findall('<li.*?>(.*?)</li>',html,re.S)
print(results)
for result in results:
    print(result.strip())#把换行符去掉

下图是去掉a标签后的html文本:
在这里插入图片描述
在这个基础上findall的结果:
在这里插入图片描述
可以看到,在适当的时候,借助sub方法可以起到事半功倍的效果。

re.compile

将正则字符串编译成正则表达式对象,以便复用该匹配模式。

import re

content='''Hello 1234567 World_This 
is a Regex Demo'''
pattern=re.compile('Hello.*Demo',re.S)
#编译成一个对象
result=re.match(pattern,content)
#原来的写法:result=re.match('Hello.*Demo',content,re.S)
print(result)

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/z714405489/article/details/83217567