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实现自动添加脚本头信息的示例代码
Sep 02 Python
Python爬虫包 BeautifulSoup  递归抓取实例详解
Jan 28 Python
Python单例模式的两种实现方法
Aug 14 Python
Python实现XML文件解析的示例代码
Feb 05 Python
python数据结构之线性表的顺序存储结构
Sep 28 Python
基于python实现从尾到头打印链表
Nov 02 Python
python manage.py runserver流程解析
Nov 08 Python
python实点云分割k-means(sklearn)详解
May 28 Python
基于TensorFlow的CNN实现Mnist手写数字识别
Jun 17 Python
浅谈keras使用中val_acc和acc值不同步的思考
Jun 18 Python
matplotlib教程——强大的python作图工具库
Oct 15 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
1 Tube Radio
2021/03/02 无线电
PHP中在数据库中保存Checkbox数据(1)
2006/10/09 PHP
介绍一些PHP判断变量的函数
2012/04/24 PHP
php开发文档 会员收费1期
2012/08/14 PHP
php类常量的使用详解
2013/06/08 PHP
PHP PDOStatement::setFetchMode讲解
2019/02/03 PHP
dojo 之基础篇
2007/03/24 Javascript
JavaScript 序列化对象实现代码
2009/12/18 Javascript
jQuery实现复选框全选/取消全选/反选及获得选择的值
2014/06/12 Javascript
js实现带圆角的两级导航菜单效果代码
2015/08/24 Javascript
AngularJS 模块化详解及实例代码
2016/09/14 Javascript
js canvas实现放大镜查看图片功能
2017/06/08 Javascript
Vue.js子组件向父组件通信的方法实例代码详解
2018/12/10 Javascript
详解一个基于套接字实现长连接的express
2019/03/28 Javascript
vue实现一个获取按键展示快捷键效果的Input组件
2021/01/13 Vue.js
js实现鼠标切换图片(无定时器)
2021/01/27 Javascript
[15:28]DOTA2 HEROS教学视频教你分分钟做大人-剧毒术士
2014/06/13 DOTA
详解python里使用正则表达式的全匹配功能
2017/10/19 Python
基于python实现学生管理系统
2018/10/17 Python
python tkinter canvas使用实例
2019/11/04 Python
python+requests接口压力测试500次,查看响应时间的实例
2020/04/30 Python
Python HTMLTestRunner库安装过程解析
2020/05/25 Python
python 获取剪切板内容的两种方法
2020/11/28 Python
html5手机键盘弹出收起的处理
2020/01/20 HTML / CSS
Mixbook加拿大:照片书,照片卡,剪贴簿,年历和日历
2017/02/21 全球购物
美国体育用品商店:Paragon Sports
2017/10/08 全球购物
Chicco婴儿用品美国官网:汽车座椅、婴儿推车、高脚椅等
2018/11/05 全球购物
碧欧泉Biotherm加拿大官方网站:法国高端护肤品牌
2019/10/18 全球购物
仓库管理制度
2014/01/21 职场文书
优秀应届毕业生推荐信
2014/02/18 职场文书
2014年中职班主任工作总结
2014/12/16 职场文书
消防隐患整改通知书
2015/04/22 职场文书
同乡会致辞
2015/07/30 职场文书
有关信念的名言语录集锦
2019/12/06 职场文书
Golang: 内建容器的用法
2021/05/05 Golang
Python使用openpyxl模块处理Excel文件
2022/06/05 Python