python贪婪匹配和非贪婪匹配_Python关于正则贪婪与非贪婪特性的详解

本文详细讲解了Python正则表达式中贪婪匹配的原理和非贪婪模式的应用,通过实例演示了如何避免过度匹配问题,以及如何利用问号和预查符号实现精确控制。涵盖了贪婪模式的不足、非贪婪匹配的使用场景,以及特殊语法如(?=)和(?!)的应用。
摘要由CSDN通过智能技术生成

这篇文章主要介绍了Python正则表达式中贪婪/非贪婪特性的相关资料,文中通过示例代码介绍的很详细,对大家具有一定的参考价值,需要的朋友下面来一起看看吧。

之前已经简单介绍了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)

【相关推荐】

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值