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 相关文章推荐
Django与JS交互的示例代码
Aug 23 Python
PyCharm在新窗口打开项目的方法
Jan 17 Python
Python实现html转换为pdf报告(生成pdf报告)功能示例
May 04 Python
Pandas之Fillna填充缺失数据的方法
Jun 25 Python
python中PS 图像调整算法原理之亮度调整
Jun 28 Python
Python企业编码生成系统之系统主要函数设计详解
Jul 26 Python
django中上传图片分页三级联动效果的实现代码
Aug 30 Python
python实现WebSocket服务端过程解析
Oct 18 Python
Python数据可视化处理库PyEcharts柱状图,饼图,线性图,词云图常用实例详解
Feb 10 Python
浅析Python __name__ 是什么
Jul 07 Python
python利用appium实现手机APP自动化的示例
Jan 26 Python
Python中的流程控制详解
Feb 18 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
DC游戏Steam周三特惠 《蝙蝠侠》阿卡姆系列平史低
2020/04/09 欧美动漫
php下将XML转换为数组
2010/01/01 PHP
CI框架中集成CKEditor编辑器的教程
2014/06/09 PHP
PHP实现合并discuz用户
2015/08/05 PHP
PHP批量去除BOM头内容信息代码
2016/03/11 PHP
thinkPHP5框架实现基于ajax的分页功能示例
2018/06/12 PHP
TP5.0框架实现无限极回复功能的方法分析
2019/05/04 PHP
laravel接管Dingo-api和默认的错误处理方式
2019/10/25 PHP
分析Node.js connect ECONNREFUSED错误
2013/04/09 Javascript
鼠标焦点离开文本框时验证的js代码
2013/07/19 Javascript
没有document.getElementByName方法
2013/08/19 Javascript
JavaScript Function函数类型介绍
2015/04/08 Javascript
个人总结的一些JavaScript技巧、实用函数、简洁方法、编程细节
2015/06/10 Javascript
javascript实现粘贴qq截图功能(clipboardData)
2016/05/29 Javascript
jQuery stop()用法实例详解
2016/07/28 Javascript
使用Node.js给图片加水印的方法
2016/11/15 Javascript
Javascript ES6中数据类型Symbol的使用详解
2017/05/02 Javascript
Angular 4.X开发实践中的踩坑小结
2017/07/04 Javascript
纯js实现页面返回顶部的动画(超简单)
2017/08/10 Javascript
js中innerText/textContent和innerHTML与target和currentTarget的区别
2019/01/21 Javascript
[01:03]悬念揭晓 11月26日DOTA2完美盛典不见不散
2017/11/23 DOTA
[05:24]TI9采访——教练
2019/08/24 DOTA
关于python写入文件自动换行的问题
2018/06/23 Python
Python定时任务工具之APScheduler使用方式
2019/07/24 Python
flask框架配置mysql数据库操作详解
2019/11/29 Python
tensorflow 变长序列存储实例
2020/01/20 Python
python 爬取免费简历模板网站的示例
2020/09/27 Python
建筑学推荐信
2013/11/03 职场文书
产品销售员岗位职责
2013/12/18 职场文书
物流专业大学的自我评价
2014/01/11 职场文书
初中优秀教师事迹材料
2014/08/18 职场文书
2015年基层党组织公开承诺书
2015/01/21 职场文书
2015年社区矫正工作总结
2015/04/21 职场文书
民事诉讼答辩状范文
2015/05/21 职场文书
学习经验交流会演讲稿
2015/11/02 职场文书
2016春季幼儿园大班开学寄语
2015/12/03 职场文书