正则表达式(三)——高级用法:search,findall,sub,split

进阶部分在这里:正则表达式(二)——进阶之匹配分组

4. search用法

上面我们学习了re模块的match用法,下面我们来学习下re模块中search用法!(其实也算不上高级用法啦)

match和search对比:

match的一个特点就是从左向右完整的去匹配,多出来的不管,少了就不行;

search是在给定字符串当中去搜索的符合正则表达式的内容。

match和search的语法都一样,都为re.xxxx(正则表达式,字符串)

 需求:在一段文字中,比如 "'文章篇幅为1314521个字" ,我们如何查找得到数字digit部分?

分析:关于数字的描述可以表达为 r'\d+'。

>>> result = re.search(r'\d+','文章篇幅为1314521个字')
>>> result.group()
'1314521'

这样不就把数字部分提取出来了么。你可以定义自己的正则表达式,提取想要的内容。

======================================================================================

前面在正则表达式(一)——基础之匹配字符,数量,边界中的《边界》部分,我说过一句话:^(匹配字符串开头)这个效果在match中不是很明显,原因match就是从左到右开始匹配的,它做的是匹配工作。

但是在search里,^ 效果却是十分明显的,比如当我们想要匹配以数字开头的,正则表达式为:

r'^\d+'
>>> result = re.search(r'^\d+','文章篇幅为1314521个字')
None

这样的结果是None,未能匹配。

 

  • Question one?

search和match都是一次性匹配,即只要匹配到内容就立马结束,看如下代码:

>>> result = re.search(r'\d+','文章篇幅为1314521个字,共234页')
>>> result.group()
'1314521'

按正常理来说,应该返回给我'1314521'和'234'啊,这就是search的一次性匹配。那有没有全部匹配的用法呢?答案:of course。就是下面的findall用法

5. findall用法

需求:在一段文字中,比如 "'文章篇幅为1314521个字,共234页,有1000张图" ,找到所有数字digit部分

分析:查找数字的正则表达式为r'\d+'

>>> result = re.findall(r'\d+','文章篇幅为1314521个字,共234页,有1000张图')
>>> result
['1314521', '234', '1000']

注意:findall返回的对象就是list类型的,支持list的所有操作

6. sub 将匹配到的数据进行替换(substitute不是sub减)

先看看sub函数:re.sub(pattern, repl, string, count=0, flags=0)

其中三个必选参数:pattern, repl, string

两个可选参数:count, flags

  • pattern,表示正则中的模式字符串
  • repl,就是replacement,被替换,的字符串的意思。repl可以是字符串,也可以是函数
  • string,即表示要被处理,要被替换的那个string字符串。

需求1:在班级模拟考试分数表上,需要对某个同学的数学成绩加20分,英语成绩加20分,比如该同学分数表内容为:”math=60,English=50"

分析:我们首先需要匹配到数字部分。再拿到数字的当前数值,在这基础上加上对应的值。先匹配再替换,sub函数可以同时完成这两件事。

======================================================================================

我们,先来简化下需求,展示repl是字符串的情况。直接把math=60,English=50的数值部分直接替换为80分:

>>> ret = re.sub(r'\d+','80','math=60,English=50')
>>> ret             #返回的是str类型
'math=80,English=80'

这样太弱智了,而且把English的数值也变成了80

======================================================================================

 因此,我们需要定义函数来处理这个逻辑,展示repl是函数的情况:

定义函数用交互环境不方便,我用IDE吧!

import re
'''result是先作查找操作,结束后得到的结果,与match或者search得到的result无异,实质上sub方法实现包括了search方法'''
def replace(result):  #定义替换函数,返回处理后的str
    print('the digit value is:',result.group())
    r = int(result.group()) + 20
    return str(r)    #转成str类型

r = re.sub(r'\d+',replace,'math=60,English=50')
print(r)

'''
output:
the digit value is: 60
the digit value is: 50
math=80,English=70
'''

======================================================================================

我们再来看个sub的实际需求应用:

需求2:在下面的python工程师招聘要求网页源码文本中,我们需要把标签都过滤掉,只留下文本。即去掉,<html>,</html>,<p>,</p>,<br/>,<span>,</span>等标签。

<html>
<p>##python开发工程师</p>
<p><span>+ python爬虫工程师</span></p>
<p>负责大规模文本、图像等数据的抓取、结构化信息的提取、质量识别等工作。</p>
<p>1. 开发分布式网络爬虫</p>
<p>2. 提取结构化信息</p>
<p>3. 识别结构化信息的质量</p>
<p>岗位要求:</p>
<p>1. 熟悉 Linux 开发环境,熟练使用 Shell</p>
<p>2. 熟悉 高并发、高性能分布式系统</p>
<p>3. 熟悉 HTTP协议,熟悉 HTML,JavaScript,XPath</p>
<p>4. 熟悉 网络协议</p>
<p>5. 从事 Python 开发 1年及以上</p>
<p>6. 熟练使用 Python 进行抓取及格式化信息提取</p>
<p>岗位职责:</p>
<p>1、根据实际任务,进行高校大数据业务开发,满足市场需求;</p>
<p>2、能独立完成项目开发文档的撰写工作;</p>
<p>3、能够与开发团队中其它成员有效沟通,包括其它工程师、项目经理、产品以及测试,设计出高性能、可扩展而且符合用户需求的方案;</p>
<p>4、对新技术具有较强的研究和解决问题的能力,并能够共享其成果在小组/部门内推广;</p>
<p>5、能够和小组中帮助其它工程师讨论并解决疑难问题;</p>
<p>6、按时保质保量完成产品开发任务;</p>
<p>7、热衷研究新兴技术,对产品进行持续优化。</p>
<p><br/></p>
<p>任职资格:</p>
<p>1、两年以上稳定开发经验,熟悉python语言</p>
<p>2、熟悉Linux操作,使用git进行版本控制管理,有nginx配置部署经验;</p>
<p>3、熟悉django tornado flask 任一python开发框架,懂代码调试并能持续优化;</p>
<p>4、熟悉HTTP协议,能开发符合RESTful设计思想的接口;</p>
<p>5、有mysql.mongodb.redis等常用数据库的使用经验;</p>
<p>6、优良的代码注释习惯,并能编写有条理的开发文档。</p>
<p>7、使用过运维工具,能自行编写简单的SHELL脚本</p>
<p>8、对技术精进有要求,愿意学习大数据相关知识,并付诸实践。</p>
<p><br/></p><p><br/></p><p><br/></p>
<p>+ Python研发工程师</p><p>要求:</p>
<p>1.	全职类工作2-4(包含)年开发经验</p>
<p>2.	Python基础扎实,熟悉常用的类库</p>
<p>3.	掌握Tornado、Django、Flask其中任一web框架,至少两年左右的web开发经验</p>
<p>4.	熟悉常用的工具如Redis,Memcached,Mongodb,Mysql,Nginx等的基本原理和使用</p><p>5.	掌握linux环境下的开发和部署,掌握gitlab的使用</p>
<p>6.	熟悉常用的数据结构、算法和设计模式等</p>
</html>

分析:首先应该分析出标签的特征,写出正则表达式。把标签内容替换为空字符串“”就可以啦。乍一看,标签是<>包括的,于是得出正则表达式:

r'<.+>'
>>> s = '''把上面内容copy下来,太多啦,占屏幕'''
>>> re.sub(r'<.+>','',s)       #结果是一堆'\n',哈哈(贪婪模式)
'\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'

'''再看看下面的运行结果,就多了个?(非贪婪模式)'''
>>> re.sub(r'<.+?>','',s)       #就能得到正确结果
'\n##python开发工程师\n+ python爬虫工程师\n负责大规模文本、图像等数据的抓取、结构化信息的提取、质量识别等工作。\n1. 开发分布式网络爬虫\n2. 提取结构化信息\n3. 识别结构化信息的质量\n岗位要求:\n1. 熟悉 Linux 开发环境,熟练使用 Shell\n2. 熟悉 高并发、高性能分布式系统\n3. 熟悉 HTTP协议,熟悉 HTML,JavaScript,XPath\n4. 熟悉 网络协议\n5. 从事 Python 开发 1年及以上\n6. 熟练使用 Python 进行抓取及格式化信息提取\n岗位职责:\n1、根据实际任务,进行高校大数据业务开发,满足市场需求;\n2、能独立完成项目开发文档的撰写工作;\n3、能够与开发团队中其它成员有效沟通,包括其它工程师、项目经理、产品以及测试,设计出高性能、可扩展而且符合用户需求的方案;\n4、对新技术具有较强的研究和解决问题的能力,并能够共享其成果在小组/部门内推广;\n5、能够和小组中帮助其它工程师讨论并解决疑难问题;

其实这里的原因就是,正则表达式默认是贪婪模式(这个我们将在下一节讲解),在量词后面直接加上一个问号?就是非贪婪模式。 

======================================================================================

除了这种非贪婪模式,还有其他方法么?

分析:那么我们换个角度去思考,标签都是字母,这不可否认吧,我们可以从这里出发。那么我们可以用正则r'<\w'>表示,但是像标签</html>,</p>是无法匹配的,那么对于标签<html>,/ 是可有可无的,用?表示,因此正则 r'/?\w' 表示,但是对于<br/>又是不匹配的,在字母后面的 / 也是可有可无的,因此,正则表达式为:

r'</?\w/?>'
>>> re.sub(r'</?\w/?>','',s)
'\n##python开发工程师\n+ python爬虫工程师\n负责大规模文本、图像等数据的抓取、结构化信息的提取、质量识别等工作。\n1. 开发分布式网络爬虫\n2. 提取结构化信息\n3. 识别结构化信息的质量\n岗位要求:\n1. 熟悉 Linux 开发环境,熟练使用 Shell\n2. 熟悉 高并发、高性能分布式系统\n3. 熟悉 HTTP协议,熟悉 HTML,JavaScript,XPath\n4. 熟悉 网络协议\n5. 从事 Python 开发 1年及以上\n6. 熟练使用 Python 进行抓取及格式化信息提取\n岗位职责:\n1、根据实际任务,进行高校大数据业务开发,满足市场需求;\n2、能独立完成项目开发文档的撰写工作;\n3、能够与开发团队中其它成员有效沟通,包括其它工程师、项目经理、产品以及测试,设计出高性能、可扩展而且符合用户需求的方案;\n4、对新技术具有较强的研究和解决问题的能力,并能够共享其成果在小组/部门内推广;\n5、能够和小组中帮助其它工程师讨论并解决疑难问题;

同样达到了效果......

7. split 根据匹配进行切割字符串,并返回列表

需求:以(:,逗号,-)来切割字符串:"language:python,php,c,cpp-java"

>>> s = "language:python,php,c,cpp-java"
>>> re.split(r':|,|-',s)
['language', 'python', 'php', 'c', 'cpp', 'java']

 

讲完了正则表达式的高级用法,上面讲sub函数时,提到了正则表达式的贪婪模式与非贪婪模式。我们接下来深入理解正则表达式的贪婪模式与非贪婪模式吧。见正则表达式(四)——贪婪与非贪婪模式

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值