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之再深点,更懂list
Sep 20 Python
Python中for循环控制语句用法实例
Jun 02 Python
WINDOWS 同时安装 python2 python3 后 pip 错误的解决方法
Mar 16 Python
使用Python的package机制如何简化utils包设计详解
Dec 11 Python
Python中字典的浅拷贝与深拷贝用法实例分析
Jan 02 Python
python pandas中DataFrame类型数据操作函数的方法
Apr 08 Python
python-str,list,set间的转换实例
Jun 27 Python
在Python中增加和插入元素的示例
Nov 01 Python
对python中的控制条件、循环和跳出详解
Jun 24 Python
详解在Python中以绝对路径或者相对路径导入文件的方法
Aug 30 Python
Pandas之read_csv()读取文件跳过报错行的解决
Apr 21 Python
Scrapy 配置动态代理IP的实现
Sep 28 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
smarty中先strip_tags过滤html标签后truncate截取文章运用
2010/10/25 PHP
php网站判断用户是否是手机访问的方法
2013/11/01 PHP
PHP、Python和Javascript的装饰器模式对比
2015/02/03 PHP
php中的异常和错误浅析
2017/05/03 PHP
JS 自定义带默认值的函数
2011/07/21 Javascript
JavaScript高级程序设计 阅读笔记(七) ECMAScript中的语句
2012/02/27 Javascript
JS敏感词过滤代码
2016/12/23 Javascript
JavaScript仿支付宝6位数字密码输入框
2016/12/29 Javascript
微信小程序中button组件的边框设置的实例详解
2017/09/27 Javascript
在Swiper内如何制作CSS3动画效果示例代码
2017/12/07 Javascript
vue vuex vue-rouert后台项目——权限路由(适合初学)
2017/12/29 Javascript
node puppeteer(headless chrome)实现网站登录
2018/05/09 Javascript
解决vue A对象赋值给B对象,修改B属性会影响到A的问题
2018/09/25 Javascript
vue filter 完美时间日期格式的代码
2019/08/14 Javascript
Python multiprocessing模块中的Pipe管道使用实例
2015/04/11 Python
使用基于Python的Tornado框架的HTTP客户端的教程
2015/04/24 Python
python批量提取word内信息
2015/08/09 Python
SVM基本概念及Python实现代码
2017/12/27 Python
python之cv2与图像的载入、显示和保存实例
2018/12/05 Python
Python面向对象程序设计中类的定义、实例化、封装及私有变量/方法详解
2019/02/28 Python
python多线程http压力测试脚本
2019/06/25 Python
python使用opencv对图像mask处理的方法
2019/07/05 Python
Python HTMLTestRunner如何下载生成报告
2020/09/04 Python
Timberland美国官网:全球领先的户外品牌
2016/08/15 全球购物
For Art’s Sake官网:手工制作的奢华眼镜
2018/12/15 全球购物
英国领先的在线高尔夫设备零售商:Golfgeardirect
2020/12/11 全球购物
材料专业毕业生求职信
2014/02/26 职场文书
保险专业大学生职业规划书
2014/03/03 职场文书
李敖北大演讲稿
2014/05/24 职场文书
环保证明
2015/06/23 职场文书
新闻发布会新闻稿
2015/07/17 职场文书
陶瓷类经典广告语集锦
2019/10/25 职场文书
Java 多态分析
2022/04/26 Java/Android
spring 项目实现限流方法示例
2022/07/15 Java/Android
python如何将mat文件转为png
2022/07/15 Python
SqlServer常用函数及时间处理小结
2023/05/08 SQL Server