首页 > 编程语言 > 详细

python正则基础入门篇-2

时间:2020-05-09 16:04:54      阅读:36      评论:0      收藏:0      [点我收藏+]

这篇写关于分组和断言的一些概念和基本使用规范。

分组的符号是"()"一对括号,分组匹配的内容会分配到的每个括号里,一般会按照从左到右分配,1为第一个括号

#以一个例子简单熟悉下分组的作用
s=<div><a href="https//support.google.com/chrome/?p=ui_hotword_search" target="_blank">更多</a><p>dfsl</p></div>
pattern1 = re.search(r<a.*>(\w+)</a>,s).group()
pattern2 = re.search(r<a.*>(\w+)</a>,s).group(0)
pattern3 = re.search(r<a.*>(\w+)</a>,s).group(1)
pattern4 = re.search(r<a.*>(\w+)</a>,s).groups()
print(pattern1)
print(pattern2)
print(pattern3)
print(pattern4)
#这里对应group(),默认会打印整个正则表达式
<a href="https//support.google.com/chrome/?p=ui_hotword_search" target="_blank">更多</a>
#这里对应group(0), 跟group()相同,都是打印整个正则
<a href="https//support.google.com/chrome/?p=ui_hotword_search" target="_blank">更多</a>
#这个就是分组1匹配到的内容
更多
#对应groups(),这个是将整个分组匹配到的内容输出成元组形式
(更多,)

 熟悉了分组后,我们需要面对一个现实问题,就是分组量太多的话,无法快速定位到分组量,所以又引出一个自定义分组的功能

 以(?P<组名>pattern)为分组格式,这样只用匹配组名就定位到该分组。

 实际演练:

#提取Ip地址
s = "ip=‘230.192.168.78‘,version=‘1.0.0‘"
#自定义了一个“G”的组
matcher = re.search(r"ip=‘(?P<G>\d+\.\d+\.\d+\.\d+).*",s)
#直接定位匹配
print(matcher.group(G))
#out
230.192.168.78
 

 加深对分组的理解:正则表达式中用"()"表示一个分组,然后你可以对这个分组进行操作,最常用的就是重复操作。

 要注意的是,只有"()"才能定义组,"{}"用来定义重复操作

 当用"()"定义一个正则表达式后,正则引擎会把这些"()"按照顺序编号,存入缓存。这样后续需要对组操作就可以直接引用,看到的"\1、\2"就是对之前的分组重复引用,值得注意

 的是"\0"是正则字符串本身。

 加深理解:

#利用交换字符串位置
s1 = "abc.def"
sb = re.sub(r(\w+)\.(.*),r\2.\1,s1)
print(sb)
#利用分组后向引用,这样就可以直接在后面用\number引用,无需书写完整分组内容
#首先模拟不用后向引用
s2 = go go go
pattern = r(?P<name>\w+)\s+(?P=name)\s+(?P=name)
mat = re.search(pattern,s2)
print(mat.group(name))
print(mat.group(1))
# print(mat.group(2)) # 报错,因为只定义了一个组,后面是引用定义的,并没有新增
# print(mat.group(3)) # 同理
print(mat.groups())  # 将匹配到的分组结果输出成一个元祖
print(mat.group(0))  # 这个不解释了,打印整个r‘表达式‘

 接下采用后向引用  

pattern1 = r(?P<new>.+)\s\1\s\1
mat2 = re.search(pattern1,s2)
print(mat2.groups())  #输出匹配的所有组
print(mat2.group())   #输出整个正则表达式Regular_expression
#output 输出结果很明显得到了,组的结果和整个正则
(go,)  
go go go

-------------------------------

-------------------------------

 接下来讨论断言,其实跟分组很像,但是用法上跟分组用法恰好相反,由于分组学问很多,我只写一些基本的

 --前后肯定断言,基本格式:前肯(?= patt)、后肯(?<= patt)

 一样,实例 (注:前后肯定断言同时使用,后向需提前,后前包裹)

# 这里对长字符串中文本进行提取,前后定向正则规定在这个范围内匹配  
s = "/* hi! */this is girl /* shi is beautiful */ she have 168 cm"
partten =  r(?<=/\*).*(?=\*/)  # 这里必须加上"?",否则会贪婪模式多匹配,无视前向断言。
print(re.findall(partten,s))
...
# output  贪婪
[ hi! */this is girl /* shi is beautiful ]  
# output2 惰性
[ hi! ,  shi is beautiful ]

--前后否定断言,基本格式: 前否(?! = patt) 后否 (?<!)

学习下:

#后否定断言实例,获取除了".txt"结尾的文件集
#这里用到了后向否定断言,否定结尾字符非txt。
f1 = aaa.txt
partten = r.*\..*$(?<!txt$)
print(re.findall(partten,f1)   )
#output  因为f1是txt结尾,所以没有匹配到,返回空列表
[]
#前向否定断言匹配 开头非数字的文件集
f1 = aaa.txt
# "?!"表示非,"\d+"表示至少一个数字,^()表示以之前的规则开头,整体理解:文件开头一个数字都没有的文件集
print(re.findall(r^(?!\d+).*,1word.txt)) #这里"1"打头自然符合了前非的规则,被排除
print(re.findall(r^(?!\d*).*,f1)) #这里区别于"+","*"至少0个数字,由于f1是字母开头(没有数字正好是0),被前否排除
print(re.findall(r^(?!\d+).*,f1)) #这里区别于"*","+"至少一个数字,加前否成一个数字都没有的文件名,对应下面输出
#out 发现三个结果,值得仔细思考下
[]          
[]
[aaa.txt]

  前后向否定断言确实有点绕,很烧脑,可能是本人逻辑思维能力问题,但是可以大致这样理解,就是前后否定断言总体逻辑是 排除partten,就是除了的意思。可以这么理解。

# 提取不以数字开头和py结尾的文件
n = test.py
m = test.txt
print(re.findall(r^(?!\d+).+\..*$(?<!py$),n))
#output  由于前后断言必须满足才会输出,但是前向满足,后向不满足,因为py被后向排除
[]
print(re.findall(r^(?!\d+).+\..*$(?<!py$),m))
#out 很明显,前向否定断言否定至少有一个数字开头的文件,后否否定py结尾,test.txt都不包括,所以被匹配到
[test.txt]

整个断言分组基础就这么多内容,后续会对更复杂的断言进行练习。

参考:https://www.cnblogs.com/misswjr/p/9852574.html

 

 

python正则基础入门篇-2

原文:https://www.cnblogs.com/riNgo-joy0/p/assert_one.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!