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的文件类型
May 30 Python
Python面向对象编程中关于类和方法的学习笔记
Jun 30 Python
Python控制多进程与多线程并发数总结
Oct 26 Python
python实现决策树分类(2)
Aug 30 Python
python pandas消除空值和空格以及 Nan数据替换方法
Oct 30 Python
Python图像滤波处理操作示例【基于ImageFilter类】
Jan 03 Python
Python计算一个点到所有点的欧式距离实现方法
Jul 04 Python
python递归法解决棋盘分割问题
Jul 17 Python
基于python实现的百度新歌榜、热歌榜下载器(附代码)
Aug 05 Python
python定时任务 sched模块用法实例
Nov 04 Python
pytorch使用tensorboardX进行loss可视化实例
Feb 24 Python
Python学习开发之图形用户界面详解
Aug 23 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
微信公众号点击菜单即可打开并登录微站的实现方法
2014/11/14 PHP
php实现遍历多维数组的方法
2015/11/25 PHP
php使用preg_match()函数验证ip地址的方法
2017/01/07 PHP
php检测mysql表是否存在的方法小结
2017/07/20 PHP
JavaScript入门教程(8) Location地址对象
2009/01/31 Javascript
基于JQuery实现的类似购物商城的购物车
2011/12/06 Javascript
DOM和XMLHttpRequest对象的属性和方法整理
2012/01/04 Javascript
Extjs显示从数据库取出时间转换JSON后的出现问题
2012/11/20 Javascript
JavaScript实现的简单拖拽效果
2015/06/01 Javascript
聊一聊jQuery插件uploadify使用方法
2016/08/24 Javascript
Bootstrap学习笔记之环境配置(1)
2016/12/07 Javascript
nodejs连接mysql数据库及基本知识点详解
2018/03/20 NodeJs
浅谈在node.js进入文件目录的问题
2018/05/13 Javascript
解决Vue打包后访问图片/图标不显示的问题
2019/07/25 Javascript
js布局实现单选按钮控件
2020/01/17 Javascript
vue 通过绑定事件获取当前行的id操作
2020/07/27 Javascript
JavaScript中window和document用法详解
2020/07/28 Javascript
js通过canvas生成图片缩略图
2020/10/02 Javascript
[23:18]Spirit vs Liquid Supermajor小组赛A组 BO3 第二场 6.2
2018/06/03 DOTA
[00:47]DOTA2荣耀之路6:天火,天火!
2018/05/30 DOTA
分析Python的Django框架的运行方式及处理流程
2015/04/08 Python
Python中List.index()方法的使用教程
2015/05/20 Python
利用aardio给python编写图形界面
2017/08/21 Python
用Anaconda安装本地python包的方法及路径问题(图文)
2019/07/16 Python
Python scipy的二维图像卷积运算与图像模糊处理操作示例
2019/09/06 Python
python内置模块collections知识点总结
2019/12/19 Python
PyCharm如何导入python项目的方法
2020/02/06 Python
Ubuntu配置Pytorch on Graph (PoG)环境过程图解
2020/11/19 Python
详解HTML5中download属性的应用
2015/08/06 HTML / CSS
客房主管岗位职责
2013/12/09 职场文书
说明书范文
2014/05/07 职场文书
消防安全宣传标语
2014/06/07 职场文书
党的群众路线教育实践活动个人自我剖析材料
2014/10/07 职场文书
部队2014年终工作总结
2014/11/27 职场文书
婚礼女方父母答谢词
2015/01/04 职场文书
高三复习计划
2015/01/19 职场文书