python正则分组匹配和贪婪非贪婪的使用

本文深入解析正则表达式的高级应用,包括分组、引用、贪婪与非贪婪匹配等核心概念,通过多个实例演示如何在Python中进行精确的字符串匹配。

正则表达式匹配分组等其他的情况

字符功能
|匹配左右任意一个表达式
(ab)将括号中字符作为一个分组,可以和|一起使用(ab|cd)表示匹配括号内分组中的一个
\num引用分组num匹配到的字符串
(?P<name>)分组起别名
(?P=name)引用别名为name分组匹配到的字符串

 案例演示1:

import  re

pattern = '^M?M?M?(CM|CD|D?C?C?C?)$'
str = 'MMDCC'
s= re.search(pattern,str)
print(s.group())  #MMDCC,将()做一个分组,然后|表示匹配其左右任意一个表达式

str1 ='MCMCD'
s1 = re.search(pattern,str1)
print(s1.group()) #匹配失败,因为CM和DC在|的左右,只可以匹配其中之一

案例演示2:

import  re

pattern ='^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$'
s1 = re.search(pattern, 'MDLV')
print(s1.group())  #MDLV.第一个M匹配,第一个括号匹配D.第二个括号L.第三个括号V.

s2 = re.search(pattern,'')
print(s2.group()) #匹配成功空串.第一个M可以为空,第一个括号DC可以为空,后面同理

s3 = re.search(pattern, 'MMDCLXVI')
print(s3.group())  #MMDCLXVI

s4 = re.search(pattern, 'MMMDCCCLXXXVIII')
print(s4.group()) #MMMDCCCLXXXVIII

s5 = re.search(pattern,'I')
print(s5.group()) #I 前面为空,最后一个括号匹配I

案例3:group的使用补充 

import  re
'''
group()将匹配的结果直接以字符串的形式返回
groups()将正则匹配中的分组()匹配结果以元组形式返回
group(1) 将groups分组匹配的结果分别取出,就是第一个()的内容,同理group(2)就是第二个()内容
'''
phonePattern =  re.compile(r'^\D*(\d{3})\D*(\d{3})\D*(\d{4})\D*(\d*)$')
s1 =  phonePattern.search('(800)5551212 ext.1234')

#注意下面group(),groups(),group(1)的结果
print(s1.group()) #(800)5551212 ext.1234
print(s1.groups())  #('800', '555', '1212', '1234')
print(s1.group(1)) #800

案例4:\num分组匹配的使用,好多人没搞明白 

import re
#目标中列表里匹配出<html><h1>www.bai.com</h1></html>

labels = ["<html><h1>www.bai.com</h1></html>", "<html><h1>www.sina.cn</h2></html>"]

for label in labels:
    ret = re.match(r"<(\w*)><(\w*)>.*</\2></\1>", label)
    #这里所谓的\2指的是第二个分组匹配的结果,因为一个()表示一个分组,也就是正则里的第二个括号
    # 所以\2代表的分组就是第二个(\w*)匹配的结果,这里也就是h1.

    # ret1 = re.match(r"<(\w*)><(\d*)>.*</\2></\1>", label)
    #注意如果这里讲第二个()换成(\d*),就会匹配失败
    if ret:
        print("%s 是符合要求的标签" % ret.group())
    else:
        print("%s 不符合要求" % label)
'''
<html><h1>www.bai.com</h1></html> 是符合要求的标签
<html><h1>www.sina.cn</h2></html> 不符合要求
'''

总结:

^ 匹配字符串开始位置。
• $ 匹配字符串结束位置。
• \b 匹配一个单词边界。
• \d 匹配一个数字。
• \D 匹配一个任意的非数字字符。
• x? 匹配可选的 x 字符。换句话说,就是 0 个或者 1 个 x 字符。
• x* 匹配 0 个或更多的 x。
• x+ 匹配 1 个或者更多 x。
• x{n,m} 匹配 n 到 m 个 x,至少 n 个,不能超过 m 个。
• (a|b|c) 匹配单独的任意一个 a 或者 b 或者 c。
• (x) 这是一个组,它会记忆它匹配到的字符串。你可以用
re.search 返回的匹配对象的 groups()函数来获取到匹配的值

python正则匹配的贪婪和非贪婪

Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;

非贪婪则相反,总是尝试匹配尽可能少的字符。

在"*","?","+","{m,n}"后面加上?,使贪婪变成非贪婪。

>>> s="This is a number 234-235-22-423"
>>> r=re.match(".+(\d+-\d+-\d+-\d+)",s)
>>> r.group(1)
'4-235-22-423'
>>> r=re.match(".+?(\d+-\d+-\d+-\d+)",s)
>>> r.group(1)
'234-235-22-423'
>>>

正则表达式模式中使用到通配字,那它在从左到右的顺序求值时,会尽量“抓取”满足匹配最长字符串,在我们上面的例子里面,“.+”会从字符串的启始处抓取满足模式的最长字符,其中包括我们想得到的第一个整型字段的中的大部分,“\d+”只需一位字符就可以匹配,所以它匹配了数字“4”,而“.+”则匹配了从字符串起始到这个第一位数字4之前的所有字符。

解决方式:非贪婪操作符“?”,这个操作符可以用在"*","+","?"的后面,要求正则匹配的越少越好。

>>> re.match(r"aa(\d+)","aa2343ddd").group(1)
'2343'
>>> re.match(r"aa(\d+?)","aa2343ddd").group(1)
'2'
>>> re.match(r"aa(\d+)ddd","aa2343ddd").group(1) 
'2343'
>>> re.match(r"aa(\d+?)ddd","aa2343ddd").group(1)
'2343'
>>>

统一声明:关于原创博客内容,可能会有部分内容参考自互联网,如有原创链接会声明引用;如找不到原创链接,在此声明如有侵权请联系删除哈。关于转载博客,如有原创链接会声明;如找不到原创链接,在此声明如有侵权请联系删除哈。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

涤生大数据

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值