re模块的快速使用
# 导入re模块
import re
# 使用match方法进行匹配操作
result = re.match(正则表达式,要匹配的字符串)
# 如果上一步匹配到数据的话,可以使用group方法来提取数据
result.group()
re.match是用来进行正则匹配检查的方法,若字符串匹配正则表达式,则match方法返回匹配对象(Match Object),否则返回None(注意不是空字符串"")。
匹配对象Macth Object具有group方法,用来返回字符串的匹配部分。
匹配以itcast开头的语句
import re
result = re.match("itcast","itcast.cn")
result # <_sre.SRE_Match object; span=(0, 6), match='itcast'>
result.group() # itcast
注意:match只能匹配以xxx开头的字符串,而不能匹配xxx位于中间的字符串格式。但是我们可以使用分组的方法,到时候通过分组序号引用想要的内容(见python贪婪和非贪婪案例)
表示字符
在上一小节中,了解到通过re模块能够完成使用正则表达式来匹配字符串
本小节,将要讲解正则表达式的单字符匹配
字符 | 功能 |
---|---|
. | 匹配任意1个字符(除了\n) |
[ ] | 匹配[ ]中列举的字符 |
\d | digit。匹配数字,即0-9。 等价于[0-9] |
\D | 匹配非数字,即不是数字。 等价于[^0-9] |
\s | 匹配空白,即 空格,tab键,换行\n |
\S | 匹配非空白 |
\w | word。匹配单词字符,即a-z、A-Z、0-9、_ 。等价于[a-zA-Z0-9_] |
\W | 匹配非单词字符。 等价于[^a-zA-Z0-9_] |
>>> re.match('\w','9as')
<_sre.SRE_Match object; span=(0, 1), match='9'>
>>> re.match('\w','_as')
<_sre.SRE_Match object; span=(0, 1), match='_'>
>>> re.match('\w','+as')
>>> None
表示数量
匹配多个字符的相关格式
字符 | 功能 |
---|---|
* | 匹配前一个字符出现0次或者无限次,即可有可无。 >=0 |
+ | 匹配前一个字符出现1次或者无限次,即至少有1次。 >=1 |
? | 匹配前一个字符出现1次或者0次,即要么有1次,要么没有 |
{m} | 匹配前一个字符出现m次 |
{m,} | 匹配前一个字符至少出现m次 |
{m,n} | 匹配前一个字符出现从m到n次 |
可以用括号将多个字符当成一个字符来匹配。事实上使用括号就变成了一个group。
>>> re.match('(123){2}','123123789')
<_sre.SRE_Match object; span=(0, 6), match='123123'>
>>> re.match('(123){2}','123123789').group(1)
'123'
>>> re.match('123{2}','123123')
>>> None
>>> re.match('123{2}','1233123')
<_sre.SRE_Match object; span=(0, 4), match='1233'>
表示边界
字符 | 功能 |
---|---|
^ | 匹配字符串开头,因此必须写在开头 |
$ | 匹配字符串结尾,因此必须写在结尾 |
\b | 匹配一个单词的边界 |
\B | 匹配非单词边界 |
匹配分组
字符 | 功能 |
---|---|
| | 匹配左右任意一个表达式 |
(ab) | 将括号中字符作为一个分组 |
\num |
引用分组num匹配到的字符串 |
(?P<name>) |
分组起别名 |
(?P=name) | 引用别名为name分组匹配到的字符串 |
1.匹配出0-100之间的数字
ret = re.match("[1-9]?\d$|100","78")
ret.group()
2.匹配html标签里的文本
>>> result = re.match(r"<h1>(.*)</h1>","<h1>我爱python</h1>")
>>> result.group() # 等价于 result.group(0)
'<h1>我爱python</h1>'
>>> result.group(1) # 引用第一个分组
'我爱python'
3.\num
的用法
>>> result = re.match(r"<(.*)><(.*)>.*</\2></\1>","<html><h1>我爱python</h1></html>")
>>> result.group()
'<html><h1>我爱python</h1></html>'
>>> result.group(1)
'html'
4.(?P<name>)
的使用
>>> result = re.match(r"<h1>(?P<text>.*)</h1>","<h1>我爱python</h1>")
>>> result
<_sre.SRE_Match object; span=(0, 17), match='<h1>我爱python</h1>'>
>>> result.group('text')
'我爱python'
5.(?P=name)
的使用
>>> result = re.match(r"<(?P<key1>.*)><(?P<key2>.*)>.*</(?P=key2)></(?P=key1)>","<html><h1>我爱python</h1></html>")
>>> result.group()
'<html><h1>我爱python</h1></html>'
>>> result.group(1)
'html'
原始字符串
补充:print
打印输出时会对字符串中的\
进行转义。但是字符串本质上还是带有\
。如果字符串前面带有r
,则可以避免转义。
>>> mm = "c:\\a\\b\\c"
>>> mm
'c:\\a\\b\\c'
>>> print(mm)
c:\a\b\c
>>> print(r"c:\\a\\b\\c")
c:\\a\\b\\c
>>> print(mm)
c:\a\b\c
>>> r"c:\\a\\b\\c"
'c:\\\\a\\\\b\\\\c'
>>> re.match("c:\\\\",mm).group()
'c:\\'
>>> ret = re.match("c:\\\\",mm).group()
>>> print(ret)
c:\
>>> ret = re.match("c:\\\\a",mm).group()
>>> print(ret)
c:\a
>>> ret = re.match(r"c:\\a",mm).group()
>>> print(ret)
c:\a
>>> ret = re.match(r"c:\a",mm).group()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'
>>>
说明
Python中字符串前面加上 r 表示原生字符串
,
与大多数编程语言相同,正则表达式里使用"\"作为转义字符
,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"",那么使用编程语言表示的正则表达式里将需要4个反斜杠"\":前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。
Python里的原生字符串很好地解决了这个问题,有了原始字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。
>>> ret = re.match(r"c:\\a",mm).group()
>>> ret
'c:\\a'
>>> print(ret)
c:\a
re模块的高级用法
search,匹配到第一个就返回,不关心后面有没有满足规则的
需求:匹配出文章阅读的次数
>>> import re
>>>
>>> ret = re.search(r"\d+", "阅读次数为 9999")
>>> ret.group()
'9999'
findall
需求:统计出python、c、c++相应文章阅读的次数
import re
ret = re.findall(r"\d+", "python = 9999, c = 7890, c++ = 12345")
print(ret) # 返回列表,不需要使用group
运行结果:
['9999', '7890', '12345']
sub 将匹配到的数据进行替换,默认匹配所有满足规则的
>>> ret = re.sub(r"\d+", '998', "python = 997 java = 200")
>>> ret
'python = 998 java = 998'
需求:从下面的字符串中取出文本
<div>
<p>岗位职责:</p>
<p>完成推荐算法、数据统计、接口、后台等服务器端相关工作</p>
<p><br></p>
<p>必备要求:</p>
<p>良好的自我驱动力和职业素养,工作积极主动、结果导向</p>
<p> <br></p>
<p>技术要求:</p>
<p>1、一年以上 Python 开发经验,掌握面向对象分析和设计,了解设计模式</p>
<p>2、掌握HTTP协议,熟悉MVC、MVVM等概念以及相关WEB开发框架</p>
<p>3、掌握关系数据库开发设计,掌握 SQL,熟练使用 MySQL/PostgreSQL 中的一种<br></p>
<p>4、掌握NoSQL、MQ,熟练使用对应技术解决方案</p>
<p>5、熟悉 Javascript/CSS/HTML5,JQuery、React、Vue.js</p>
<p> <br></p>
<p>加分项:</p>
<p>大数据,数理统计,机器学习,sklearn,高性能,大并发。</p>
</div>
re.sub(r"</?\w+>","",s)
split 根据匹配进行切割字符串,并返回一个列表
需求:切割字符串“info:xiaoZhang 33 shandong”
>>> ret = re.split(r":| ","info:xiaoZhang 33 shandong")
>>> ret
['info', 'xiaoZhang', '33', 'shandong']
python贪婪和非贪婪
Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;
非贪婪则相反,总是尝试匹配尽可能少的字符。
在"*","?","+","{m,n}"后面加上?,使贪婪变成非贪婪。
>>> s="This is a number 234-235-22-423"
>>> r=re.match(".+(\d+-\d+-\d+-\d+)",s)
>>> r.group(1)
'4-235-22-423'
>>> r=re.match(".+?(\d+-\d+-\d+-\d+)",s)
>>> r.group(1)
'234-235-22-423'
>>>
正则表达式模式中使用到通配字,那它在从左到右的顺序求值时,会尽量“抓取”满足匹配最长字符串,在我们上面的例子里面,“.+”会从字符串的启始处抓取满足模式的最长字符,其中包括我们想得到的第一个整型字段的中的大部分,“\d+”只需一位字符就可以匹配,所以它匹配了数字“4”,而“.+”则匹配了从字符串起始到这个第一位数字4之前的所有字符。
解决方式:非贪婪操作符“?”,这个操作符可以用在"*","+","?"的后面,要求正则匹配的越少越好。
注意:必须满足其他条件之后才去考虑非贪婪模式
>>> re.match(r"aa(\d+)","aa2343ddd").group(1)
'2343'
>>> re.match(r"aa(\d+?)","aa2343ddd").group(1)
'2'
>>> re.match(r"aa(\d+)ddd","aa2343ddd").group(1)
'2343'
>>> re.match(r"aa(\d+?)ddd","aa2343ddd").group(1)
'2343'
>>>
练一练,字符串为:
<img data-original="https://rpic.douyucdn.cn/appCovers/2016/11/13/1213973_201611131917_small.jpg" src="https://rpic.douyucdn.cn/appCovers/2016/11/13/1213973_201611131917_small.jpg" style="display: inline;">
请提取url地址
>>> re.findall(r"https.+?\.jpg",s)
['https://rpic.douyucdn.cn/appCovers/2016/11/13/1213973_201611131917_small.jpg', 'https://rpic.douyucdn.cn/appCovers/2016/11/13/1213973_201611131917_small.jpg']
网友评论