本节实现的功能主要是要对数据进行匹配并且extract出相应的需要的数据。
知识点1:
re.findall()
首先对比和re.search()作用的区别,re.search()找到匹配的值之后只返回True和Faulse,而re.findall()在找到匹配的内容之后可以将内容extract出来,打印显示,注意返回的是一个匹配的字符串组成的列表。
举个例子:
先说明一个正则表达式:[0-9]+
表示的是最少1个,最多无限制的数字串,同样可以类比字母串等。
import re
str = 'I am 22 years old boy who had 1 Computer and 2 mobilephones'
y = re.findall('[0-9]+' , str)
print(y)
z = re.findall('[oyt]+' , str)
print(z)
输出结果为:
[‘22’, ‘1’, ‘2’]
[‘y’, ‘o’, ‘oy’, ‘o’, ‘o’, ‘t’, ‘o’, ‘o’]
注意!这里返回的并不是数字,而是字符串组成的列表!!!
这里有一个小发现,如果相连的两个单位字符串都在包含在正则表达式中,那么他们会“连着”输出打印出来。
知识点2:
Greedy Match(贪婪匹配的解读与实例)
简单的解读就是例如*和+这样的表示重复的符号,在匹配的时候向四面八方外推,并尽可能找到能够匹配的最长的字符串。举例如下:
import re
str1 = 'From: the using: 12345'
y = re.findall('^F.+:' , str1)
print(y)
这段代码的输出结果为:
[‘From: the using:’]
我们可以发现,From:这一小段代码其实也是符合正则表达式的要求的,但是最终输出的确实较长的一段,这就是Greedy Match的解释。
知识点3:
Non-Greedy Match(其实就是如何避免上一个知识点出现的情况,即输出较短的。)
这里就要在正则表达式中加入一个?
将上一个正则表达式改写为:
^F.+?:
即可,意思就是,以F开头,中间任意字符,最少出现1次,最多不限,不要进行贪婪匹配,并最终以:结尾,程序验证如下:
import re
str1 = 'From: the using: 12345'
z = re.findall('^F.+?:' , str1)
print(z)
输出结果为:
[‘From:’]
知识点4:
对于Greedy Match的进一步的理解
要求,找出mbox-short当中的所有的邮箱。
import re
#x = list() #用于存放邮箱地址
fhandle = open('mbox-short.txt')
for line in fhandle:
line = line.rstrip()
#print()
if re.search('\S+@\S+' , line):
#print('123')
x = re.findall('\S+@\S+' , line)
print(x)
从最终的输出结果也可以看出来,最终输出的是完整的邮箱地址,也可以理解为是一次贪婪搜索,以123@123.com 距离,3@1和邮箱的整体地址都是符合正则表达式的要求的,但是最终的输出时完整的邮箱,因此是贪婪匹配。
我的个人理解,贪婪匹配的起点是从非特殊符号,例如@开始的。个人理解,有待商榷。
更新:
一般来说,python正则表达式的贪婪匹配都是向后的,这里用一段实例来说明:
import re
str = 'From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008'
y = re.findall('\S+?@\S+' , str)
print(y)
该段代码的输出结果为:
[‘stephen.marquard@uct.ac.za’]
可见在@前的?没有起到作用,当我们调整代码为:
import re
str = 'From stephen.marquard@uct.ac.za Sat Jan 5 09:14:16 2008'
y = re.findall('\S+@\S+?' , str)
print(y)
该段代码的输出结果为:
[‘stephen.marquard@u’]
可见@之后的?起作用的了,因此得到相应结论。
知识点5:
圆括号不是匹配内容的一部分,但是它会告诉你提取的字符串从哪里开始到哪里结束
举例:
^From(\S+@\S+),这个正则表达式的含义就是以From为开头的,以@向两侧匹配非空格字符,一直到出现空格字符为止。
主要用到的情况是我想要用到的部分被包括在我的搜索正则表达式当中,即少于我的正则表达式。
import re
str = 'From:123@123.com: SKR~~~'
x = re.findall('^From:(\S+@\S+m)' , str)
print(x)
本例的输出结果为:
[‘123@123.com’]
需要注意的是,我一开始的时候将字符串设为:
str = 'From: Gary_Xie 123@123.com: SKR~~~'
用同样的正则表达式是检索不出相应的内容的,原因是前缀没有写全。如果写成‘From: Gary_Xie (\S+@\S)’就可以读出来了。这边还存疑
知识点6:
用正则表达式实现Dual Split的功能,(Dual Split可以参阅前面的内容)
这里需要用到的一个正则表达式为:
^From .*@([^ ]*)
这里的正则表达式里面出现了一个没见过的符号,[],这个符号是不要匹配的意思,所以说[^ ]
的意思就是不要匹配以空格为开头的(everything but)
但是需要注意的是,[0-9]是截然不同的意思,不懂可以看本节开头处。
因此整个正则表达式的意思是,^From的意思是先筛选行,然后找出以@开头,后面紧跟的不以空格开头的字符串内容。
代码举例如下:
str1 = 'From stephon.gary@hhu.cn sat jan 5:03'
z = re.findall('^From .*@([^ ]*)' , str1)
print(z)
输出结果为:
[‘hhu.cn’]
知识点7:
dollar sign
先举例代码为:
info = 'I got $10.00 today'
x = re.findall('\$[0-9.]+' , info)
print(x)
输出结果为:
[’$10.00’]
其中\$
为dollar sign,专门用于提取美元符号,[0-9.]意为包含数字0-9,小数点的字符串。注意这里\$
本身就是一个正则表达式,所以不需要^来开头。