概述
场景描述
由于项目的某一些应用场景出现了如下的需求:
A: str = “ABCABABCABABC”
B: 将其中ABC都抠出来
猛一看,这还不easy呢? 直接 ABC匹配不就出来了吗?
str = "ABCABABCABABC"
res = re.findall(r'ABC', str, re.M)
这结果不就出来了吗?
可是难就难在这边,这边的ABC并非真实的字母,而是一个泛指 。具体的str参见如下描述:
str1 = "a:bc123cdfddd1 d32sfdfds2332fsd1 n data:dsafdsfssdfsdnalert ===> virusn"
"a:bc123cdfdddd2 32sfdfds2332fsd1 n data:dsafdsfssdfsd end222end!!!!n"
"a:bc123cdfdddd3 32sfdfds2332fsd1 n data:dsafdsfssdfsdnalert===> no virusn"
"a:bc123cdfdddd3 32sfdfds2332fsd1 n data:dsafdsfssdfsdnalert===> no virusn"
"a:bc123cdfdddd2 32sfdfds2332fsd1 n data:dsafdsfssdfsd end33333end!!!n"
要求:
1、我们忽略'n',可以看到我们这边暂时分为了五行,我们要做到的事: 匹配第一、三、四行数据
2、扣除 一三四行中后面的ddd1、ddd3以及与之对应的 alert结果 no virus
实战分析
既然题目已经给出了, 那么我们就来做吧。 对于正则,我想大部分人已经非常熟悉了。
首先,我们必须忽略'n', 那么我们必须使用re库中的S,表示忽略n换行符。
sp = re.findall("a[:].*?data[:].*?alert.*?n", str1, re.S)
print sp
for i in range(len(sp)):
print sp[i]
这是我一开始给出的正则表达式,可惜得到的结果不尽人意:
a:bc123cdfddd1 d32sfdfds2332fsd1
data:dsafdsfssdfsd
alert ===> virus
a:bc123cdfdddd2 32sfdfds2332fsd1
data:dsafdsfssdfsd end222end!!!!
a:bc123cdfdddd3 32sfdfds2332fsd1
data:dsafdsfssdfsd
alert===> no virus
a:bc123cdfdddd3 32sfdfds2332fsd1
data:dsafdsfssdfsd
alert===> no virus
我们可以看到,结果分割出来 起始 和结束都没有问题,但是中间 类似于“ABABC”却被匹配上了。这不是我们想要的。
正则的前向贪婪匹配
我们都知道,正则有自己的贪婪模式,可以向后匹配最近的字段。那么我们能不能根据alert字段匹配前面最近的AB呢?
str2 = "00000aaaaa111111aaa00000bbbbb11111"
res2 = re.findall(r'(?<=0)(?!0)w+?(?=1)', str2)
print res2
#结果
['aaaaa', 'bbbbb']
可惜呢,找了全网 基本都没有我们想要的结果。于是乎 这条路基本就算走死了。
《如果以后,发现了 再回来!!!!! 》
最终解决
似乎,我们想要的都不是我们期望的,那行吧,既然前向走不通,那就最简单的方式吧。
将所有
n data
==》 data
n alert ==》 alert
那么我们的串将变为:
str1 = "a:bc123cdfddd1 d32sfdfds2332fsd1
data:dsafdsfssdfsd alert ===> virusn"
"a:bc123cdfdddd2 32sfdfds2332fsd1
data:dsafdsfssdfsd end222end!!!!n"
"a:bc123cdfdddd3 32sfdfds2332fsd1
data:dsafdsfssdfsd alert===> no virusn"
"a:bc123cdfdddd3 32sfdfds2332fsd1
data:dsafdsfssdfsd alert===> no virusn"
"a:bc123cdfdddd2 32sfdfds2332fsd1
data:dsafdsfssdfsd end33333end!!!n"
结果却依然没有改变ABABC这样的问题,
a:bc123cdfddd1 d32sfdfds2332fsd1
data:dsafdsfssdfsd alert ===> virus
a:bc123cdfdddd2 32sfdfds2332fsd1
data:dsafdsfssdfsd end222end!!!!
a:bc123cdfdddd3 32sfdfds2332fsd1
data:dsafdsfssdfsd alert===> no virus
a:bc123cdfdddd3 32sfdfds2332fsd1
data:dsafdsfssdfsd alert===> no virus
但是我们接着对上述结果 进行再匹配(原先的中间间隔换行不太好搞) 注意这边使用的re.M 不写或者re.S都会出错!!!
res = re.findall(r'a:.*?\(.*?) .*?===>(.*?)n', str1, re.M)
print res
#结果
[('ddd1', ' virus'), ('ddd3', ' no virus'), ('ddd3', ' no virus')]
总结下吧
对于这种多换行的正则匹配,没有好的办法 可以替换 换行,最后在替换回来的办法 进行匹配检索!!!!
最后附上完整代码 练习使用!
# encoding:utf-8
import re
str1 = "a:bc123cdfddd1 d32sfdfds2332fsd1
data:dsafdsfssdfsd alert ===> virusn"
"a:bc123cdfdddd2 32sfdfds2332fsd1
data:dsafdsfssdfsd end222end!!!!n"
"a:bc123cdfdddd3 32sfdfds2332fsd1
data:dsafdsfssdfsd alert===> no virusn"
"a:bc123cdfdddd3 32sfdfds2332fsd1
data:dsafdsfssdfsd alert===> no virusn"
"a:bc123cdfdddd2 32sfdfds2332fsd1
data:dsafdsfssdfsd end33333end!!!n"
sp = re.findall("a[:].*?data[:].*?alert.*?n", str1, re.S)
print sp
for i in range(len(sp)):
print sp[i]
str2 = "00000aaaaa111111aaa00000bbbbb11111"
res2 = re.findall(r'(?<=0)(?!0)w+?(?=1)', str2)
print "11111"
print res2
res = re.findall(r'a:.*?\(.*?) .*?===>(.*?)n', str1, re.M)
print res
str = "ABCABABCABABC"
res = re.findall(r'ABC', str, re.M)
print res
最后
以上就是坦率热狗为你收集整理的Python 正则是否存在前向贪婪匹配呢?的全部内容,希望文章能够帮你解决Python 正则是否存在前向贪婪匹配呢?所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复