Python正则表达式教程之三:贪婪/非贪婪特性


Posted in Python onMarch 02, 2017

之前已经简单介绍了Python正则表达式的基础与捕获,那么在这一篇文章里,我将总结一下正则表达式的贪婪/非贪婪特性。 

贪婪

默认情况下,正则表达式将进行贪婪匹配。所谓“贪婪”,其实就是在多种长度的匹配字符串中,选择较长的那一个。例如,如下正则表达式本意是选出人物所说的话,但是却由于“贪婪”特性,出现了匹配不当:

>>> sentence = """You said "why?" and I say "I don't know"."""
>>> re.findall(r'"(.*)"', sentence)
['why?" and I say "I don\'t know']

再比如,如下的几个例子都说明了正则表达式“贪婪”的特性:

>>> re.findall('hi*', 'hiiiii')
['hiiiii']
>>> re.findall('hi{2,}', 'hiiiii')
['hiiiii']
>>> re.findall('hi{1,3}', 'hiiiii')
['hiii']

非贪婪

当我们期望正则表达式“非贪婪”地进行匹配时,需要通过语法明确说明: 

      {2,5}?    捕获2-5次,但是优先次数少的匹配

在这里,问号?可能会有些让人犯晕,因为之前他已经有了自己的含义:前面的匹配出现0次或1次。其实,只要记住,当问号出现在表现不定次数的正则表达式部分之后时,就表示非贪婪匹配。 

还是上面的那几个例子,用非贪婪匹配,则结果如下:

>>> re.findall('hi*?', 'hiiiii')
['h']
>>> re.findall('hi{2,}?', 'hiiiii')
['hii']
>>> re.findall('hi{1,3}?', 'hiiiii')
['hi']

另外一个例子中,使用非贪婪匹配,结果如下:

>>> sentence = """You said "why?" and I say "I don't know"."""
>>> re.findall(r'"(.*?)"', sentence)
['why?', "I don't know"]

捕获与非贪婪

严格来说,这一部分并不是非贪婪特性。但是由于其行为与非贪婪类似,所以为了方便记忆,就将其放在一起了。 

      (?=abc) 捕获,但不消耗字符,且匹配abc

      (?!abc) 捕获,不消耗,且不匹配abc

在正则表达式匹配的过程中,其实存在“消耗字符”的过程,也就是说,一旦一个字符在匹配过程中被检索(消耗)过,后面的匹配就不会再检索这一字符了。 

知道这个特性有什么用呢?还是用例子说明。比如,我们想找出字符串中出现过1次以上的单词:

>>> sentence = "Oh what a day, what a lovely day!"
>>> re.findall(r'\b(\w+)\b.*\b\1\b', sentence)
['what']

这样的正则表达式显然无法完成任务。为什么呢?原因就是,在第一个(\w+)匹配到what,并且其后的\1也匹配到第二个what的时候,“Oh what a day, what”这一段子串都已经被正则表达式消耗了,所以之后的匹配,将直接从第二个what之后开始。自然地,这里只能找出一个出现了两次的单词。 

那么解决方案,就和上面提到的(?=abc)语法相关了。这样的语法可以在分组匹配的同时,不消耗字符串!所以,正确的书写方式应该是:

>>> re.findall(r'\b(\w+)\b(?=.*\b\1\b)', sentence)
['what', 'a', 'day']

如果我们需要匹配一个至少包含两个不同字母的单词,则可以使用(?!abc)的语法:

>>> re.search(r'([a-z]).*(?!\1)[a-z]', 'aa', re.IGNORECASE)
>>> re.search(r'([a-z]).*(?!\1)[a-z]', 'ab', re.IGNORECASE)
<_sre.SRE_Match object; span=(0, 2), match='ab'>

总结

以上就是Python正则表达式中关于贪婪的全部内容了,希望本文的内容对大家的学习或者使用python能能带来一定的帮助,如果有疑问大家可以留言交流,如果有疑问大家可以留言交流。下一篇文章,我会继续总结一下Python正则表达式re模块的一些API的用法,请继续关注三水点靠木。

Python 相关文章推荐
Python处理文本换行符实例代码
Feb 03 Python
Python cookbook(数据结构与算法)实现查找两个字典相同点的方法
Feb 18 Python
matplotlib subplots 设置总图的标题方法
May 25 Python
对numpy中向量式三目运算符详解
Oct 31 Python
python实现简单加密解密机制
Mar 19 Python
Flask框架模板继承实现方法分析
Jul 31 Python
Python递归函数 二分查找算法实现解析
Aug 12 Python
在python里创建一个任务(Task)实例
Apr 25 Python
使用keras和tensorflow保存为可部署的pb格式
May 25 Python
Python参数传递及收集机制原理解析
Jun 05 Python
python中np是做什么的
Jul 21 Python
python运行脚本文件的三种方法实例
Jun 25 Python
Python正则表达式教程之二:捕获篇
Mar 02 #Python
Python正则表达式教程之一:基础篇
Mar 02 #Python
Python单例模式实例详解
Mar 01 #Python
python实现字典(dict)和字符串(string)的相互转换方法
Mar 01 #Python
python 截取 取出一部分的字符串方法
Mar 01 #Python
详解Python中的静态方法与类成员方法
Feb 28 #Python
python基于itchat实现微信群消息同步机器人
Feb 27 #Python
You might like
PHP时间格式控制符对照表分享
2013/07/23 PHP
PHP面向对象之旅:深入理解static变量与方法
2014/01/06 PHP
Chrome Web App开发小结
2014/09/04 PHP
支持png透明图片的php生成缩略图类分享
2015/02/08 PHP
Yii2框架RESTful API 格式化响应,授权认证和速率限制三部分详解
2016/11/10 PHP
微信公众号之主动给用户发送消息功能
2019/06/22 PHP
用nodejs访问ActiveX对象,以操作Access数据库为例。
2011/12/15 NodeJs
jQuery实现页面滚动时动态加载内容的方法
2015/03/20 Javascript
浅谈JavaScript字符串拼接
2015/06/25 Javascript
Jquery实现仿京东商城省市联动菜单
2015/11/19 Javascript
jQuery+json实现动态创建复杂表格table的方法
2016/10/25 Javascript
使用3D引擎threeJS实现星空粒子移动效果
2020/09/13 Javascript
jquery中done和then的区别(详解)
2017/12/19 jQuery
layui--select使用以及下拉框实现键盘选择的例子
2019/09/24 Javascript
微信小程序可滑动周日历组件使用详解
2019/10/21 Javascript
小程序登录之支付宝授权的实现示例
2019/12/13 Javascript
js实现轮播图特效
2020/05/28 Javascript
JavaScript如何判断对象有某属性
2020/07/03 Javascript
前端性能优化建议
2020/09/17 Javascript
基于p5.js 2D图像接口的扩展(交互实现)
2020/11/30 Javascript
[01:06]DOTA2亚洲邀请赛专属珍藏-荧煌之礼
2017/03/24 DOTA
python进阶教程之函数对象(函数也是对象)
2014/08/30 Python
Python中的groupby分组功能的实例代码
2018/07/11 Python
django之对FileField字段的upload_to的设定方法
2019/07/28 Python
详解用python计算阶乘的几种方法
2019/08/14 Python
Python 元组操作总结
2019/09/18 Python
五分钟学会怎么用Pygame做一个简单的贪吃蛇
2021/01/06 Python
python 自动识别并连接串口的实现
2021/01/19 Python
RentCars.com巴西:汽车租赁网站
2016/08/22 全球购物
size?德国官方网站:英国伦敦的球鞋精品店
2018/03/17 全球购物
应届大专毕业生个人自荐信
2013/09/22 职场文书
奥林匹克运动会口号
2014/06/19 职场文书
班主任与学生安全责任书
2014/07/25 职场文书
党校毕业心得体会
2014/09/13 职场文书
2014年教师德育工作总结
2014/11/10 职场文书
2014年统计工作总结
2014/11/21 职场文书