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中文件遍历的两种方法
Jun 16 Python
Python实现队列的方法
May 26 Python
python判断字符串是否是json格式方法分享
Nov 07 Python
Python3单行定义多个变量或赋值方法
Jul 12 Python
Python解决走迷宫问题算法示例
Jul 27 Python
python 获得任意路径下的文件及其根目录的方法
Feb 16 Python
Pycharm插件(Grep Console)自定义规则输出颜色日志的方法
May 27 Python
python属于软件吗
Jun 18 Python
keras.utils.to_categorical和one hot格式解析
Jul 02 Python
Python绘图实现台风路径可视化代码实例
Oct 23 Python
只需要100行Python代码就可以实现的贪吃蛇小游戏
May 27 Python
PYTHON 使用 Pandas 删除某列指定值所在的行
Apr 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
深入eAccelerator与memcached的区别详解
2013/06/06 PHP
如何使用Gitblog和Markdown建自己的博客
2015/07/31 PHP
php生成gif动画的方法
2015/11/05 PHP
PHP代码加密的方法总结
2020/03/13 PHP
PHP数组Key强制类型转换实现原理解析
2020/09/01 PHP
ExtJS 下拉多选框lovcombo
2010/05/19 Javascript
javascript中的绑定与解绑函数应用示例
2013/06/24 Javascript
Jquery操作下拉框(DropDownList)实现取值赋值
2013/08/13 Javascript
使用javascript实现ListBox左右全选,单选,多选,全请
2013/11/07 Javascript
JavaScript设计模式之单例模式实例
2014/09/24 Javascript
javascript编写实用的省市选择器
2015/02/12 Javascript
JavaScript模拟重力状态下抛物运动的方法
2015/03/03 Javascript
html5+javascript实现简单上传的注意细节
2016/04/18 Javascript
jQuery设置聚焦并使光标位置在文字最后的实现方法
2016/08/02 Javascript
Angularjs 创建可复用组件实例代码
2016/10/09 Javascript
Angular4实现动态添加删除表单输入框功能
2017/08/11 Javascript
vue.js前后端数据交互之提交数据操作详解
2018/04/24 Javascript
jQuery使用each遍历循环的方法
2018/09/19 jQuery
在vue中使用v-bind:class的选项卡方法
2018/09/27 Javascript
使用webpack搭建vue项目实现脚手架功能
2019/03/15 Javascript
vue.js+elementUI实现点击左右箭头切换头像功能(类似轮播图效果)
2019/09/05 Javascript
Vue获取页面元素的相对位置的方法示例
2020/02/05 Javascript
[01:46]DOTA2上海特锦赛小组赛英文解说KotlGuy采访
2016/02/27 DOTA
Python编程对列表中字典元素进行排序的方法详解
2017/05/26 Python
Python如何发布程序的详细教程
2018/10/09 Python
python中强大的format函数实例详解
2018/12/05 Python
python 为什么说eval要慎用
2019/03/26 Python
django数据模型on_delete, db_constraint的使用详解
2019/12/24 Python
TensorFlow实现保存训练模型为pd文件并恢复
2020/02/06 Python
python删除指定列或多列单个或多个内容实例
2020/06/28 Python
Python根据字符串调用函数过程解析
2020/11/05 Python
如何创建一个Flask项目并进行简单配置
2020/11/18 Python
护士在校生自荐信
2014/02/01 职场文书
餐厅经理岗位职责范本
2014/02/17 职场文书
营销团队口号
2014/06/06 职场文书
2015元旦晚会主持词(开场白+结束语)
2014/12/14 职场文书