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修改Excel数据的实例代码
Nov 01 Python
零基础写python爬虫之urllib2使用指南
Nov 05 Python
python去除所有html标签的方法
May 05 Python
Python字符串切片操作知识详解
Mar 28 Python
使用anaconda的pip安装第三方python包的操作步骤
Jun 11 Python
Python对CSV、Excel、txt、dat文件的处理
Sep 18 Python
浅谈numpy生成数组的零值问题
Nov 12 Python
用Python实现大文本文件切割的方法
Jan 12 Python
详解安装mitmproxy以及遇到的坑和简单用法
Jan 21 Python
Python实现判断一个整数是否为回文数算法示例
Mar 02 Python
Django中使用session保持用户登陆连接的例子
Aug 06 Python
Python的形参和实参使用方式
Dec 24 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 字符过滤类,用于过滤各类用户输入的数据
2009/05/27 PHP
深入解析PHP的Yii框架中的缓存功能
2016/03/29 PHP
详解JavaScript的while循环的使用
2015/06/03 Javascript
javascript删除数组重复元素的方法汇总
2015/06/24 Javascript
JS实现自动变化的导航菜单效果代码
2015/09/09 Javascript
基于JQuery实现仿网易邮箱全屏动感滚动插件fullPage
2015/09/20 Javascript
js简单判断移动端系统的方法
2016/02/25 Javascript
jQuery使用$.each遍历json数组的简单实现方法
2016/04/18 Javascript
jquery实现一个全局计时器(商城可用)
2017/06/30 jQuery
vue事件修饰符和按键修饰符用法总结
2017/07/25 Javascript
Node.js使用Angular简单示例
2018/05/11 Javascript
vue、react等单页面项目部署到服务器的方法及vue和react的区别
2018/09/29 Javascript
vue搜索和vue模糊搜索代码实例
2019/05/07 Javascript
Bootstrap 时间日历插件bootstrap-datetimepicker配置与应用小结
2019/05/28 Javascript
Vue性能优化的方法
2020/07/30 Javascript
Python开发WebService系列教程之REST,web.py,eurasia,Django
2014/06/30 Python
python将回车作为输入内容的实例
2018/06/23 Python
python使用udp实现聊天器功能
2018/12/10 Python
Python turtle绘画象棋棋盘
2019/08/21 Python
python 数据生成excel导出(xlwt,wlsxwrite)代码实例
2019/08/23 Python
pymysql 开启调试模式的实现
2019/09/24 Python
python 读txt文件,按‘,’分割每行数据操作
2020/07/05 Python
CSS3改变浏览器滚动条样式
2019/01/04 HTML / CSS
html5画布旋转效果示例
2014/01/27 HTML / CSS
法国时尚品牌乐都特瑞士站:La Redoute瑞士
2016/09/05 全球购物
模具设计与制造专业推荐信
2014/02/16 职场文书
聚美优品的广告词
2014/03/14 职场文书
竞选生活委员演讲稿
2014/04/28 职场文书
求职信模板
2014/05/23 职场文书
大二学生学年自我鉴定
2014/09/12 职场文书
读书笔记格式
2015/07/02 职场文书
餐厅服务员管理制度
2015/08/05 职场文书
一个家长教育孩子的心得体会
2016/01/15 职场文书
Python中常见的导入方式总结
2021/05/06 Python
js之ajax文件上传
2021/05/13 Javascript
OpenCV-Python实现怀旧滤镜与连环画滤镜
2021/06/09 Python