第 1 章 正则表达式常用函数与方法使用
正则表达式 (regular expression) 描述了一种字符串匹配的模式( pattern ),可以用来检查
一个串是否含有某种子串。对匹配成功的字符串进行提取、拆分、替换等对应的数据处理。
几乎所有的编程语言都支持正则表达式。总体规则相同,但不同编程语言正则的处理方式却
略有不同。在整理零乱的数据时非常有用,比如做抓取网页数据、做数据验证等就经常用到。
1.01 正则表达式的两种使用方法
2. 直接使用 re 模块做正则表达式的匹配。
import re # 导入正则模块
lst1=re.findall( r'\d' , '9527' ) # 使用正则模块下的函数进行匹配
print (lst1) # 返回正则函数执行的结果
返回结果
['9', '5', '2', '7']
2. 用编译后的正则表达式去匹配字符串
import re # 导入正则模块
pattern=re.compile( r'\d' ) # 使用 compile 函数生成正则表达式对象
lst2=pattern.findall( '9527' ) # 使用正则对象的方法进行匹配
print (lst2) # 返回正则方法执行的结果
返回结果
['9', '5', '2', '7']
如果要重复使用正则表达式,则可以先将正则表达式先预编译好,也就是上面的第 2 种
方法,然后就可以重复使用了,而且效率更高。但在后面的章节讲解正则的相关函数和方法
时,我们会同时讲解这两种方式的表示方法。
不同的函数(方法)匹配成功后,返回的数据类型可能不一样。可能返回 re.Match (匹
配对象)、 list (列表)、 iterator (迭代器)、 str (字符串)等数据类型。其中 re.Match 对象中
有很多匹配成功的信息需要获取,可以通过使用 Match 对象的方法和属性来获取。后面章节
将系统讲解这些方法和属性。
1.02 从头匹配字符串( match )
Match 函数(方法)返回的是一个 re.match 对象。如果希望从字符串的开始位置匹配字
符串,则可以使用正则模块的 match 函数。如果匹配成功,就返回一个相应的匹配对象。如 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
果没有匹配,就返回 None 。
注意,如果被匹配的字符串能多次匹配成功,则只返回第 1 次匹配成功的 Match 对象。
1.02.1 re.match 函数
函数及参数说明:
re.match(pattern, string, flags=0)
pattern 匹配的正则表达式
string
要匹配的字符串。
flags
标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等
等。参见:正则表达式修饰符 - 可选标志
示例如下:
前面说过, Match 对象中有很信息可以提取,但由于现在还是初学正同阶段,所以先不
系统讲解,后面再讲。这里只讲解提取一个最常用的信息,就是提取匹配成功的字符串。比
如上面的案例中 m 代表 Match 对象 ,m[0] 则表示提取匹配成功的字符串。
1.02.2 regex.match 方法
方法及参数说明:
regex.match(string[, pos[, endpos]])
string
必选,被匹配的字符串。
pos
可选,指定起始位置。
endpos 可选,指定结束位置。
示例如下:
import re
m=re.match( r'apple' , 'apple 苹果 ' ) # 匹配以 'apple' 开头的字符串
print (m , m[ 0 ]) # 返回匹配结果
返回结果
apple 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
注意: re.compile(r'\d+') 中的“
\d+ ”表示什么意思呢?如果你是从未使用过的正则的用
户,可能很疑惑,它实际上是正则表达式中的元字符(特殊字符),表示至少有一个数字,并
尽可能匹配更多的数字。这里主要是为了稍微表现一下正则的强大,也方便举例。后面也会
详细讲解所有的元字符应用。
1.02.3 re.fullmatch 与 regex.fullmatch 的从头完全匹配
前面学习了关于 match 的函数和方法匹配方法,如果需要从最开始(或指定位置开始)
完整的匹配字符串 ,则可以使用 funllmatch 函数和 funllmatch 方法(可以从指定的位置开始)。
1.03 实例应用(提取金额)
我们来做个应用,如图 1-1 所示,将表中 A 列业绩中的金额部分,提取到 B 列,虽然有
很多方法可以完成,但现在我们希望使用刚刚学习的正则中的 match 函数(方法)来完成。
图 1-1
代码如下所示:
import re
pattern=re.compile( r'\d+' ) # 匹配多个数字
m1=pattern.match( '20kg,apple 苹果 ,123 元 ' , ) # 从最左边开始匹配
m2=pattern.match( '20kg,apple 苹果 ,123 元 ' , 13 ) # 从指定位置开始匹配
print (m1 , m1[ 0 ]) # 返回匹配结果
print (m2 , m2[ 0 ]) # 返回匹配结果
返回结果
20
123 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
1.04 任意匹配字符串( search )
之前学习的 match 是必须从起始位置开始匹配,如果不需要从起始位置匹配,则可以使
用 search 。如果匹配成功,就返回一个相应的匹配对象。如果没有匹配,就返回 None 。
注意,如果被匹配的字符串能多次匹配成功,则只返回第 1 次匹配成功的 Match 对象。
1.04.1 re.search 函数
函数及参数说明:
search(pattern, string, flags=0)
pattern 匹配的正则表达式
string
要匹配的字符串。
flags
标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
参见:正则表达式修饰符 - 可选标志
1.04.2 regex.search 方法
import re , openpyxl
wb=openpyxl.load_workbook( ' 部门业绩表 .xlsx' ) # 读取工作簿
ws=wb.active # 读取工作簿中的活动工作表
pattern=re.compile( r'\d+' ) # 正则样式
for v in ws[ 'a:a' ][ 1 :]: # 读取 A 列每个单元格的数据
m=pattern.match(v.value , 4 ) # 从指定位置开始匹配
v.offset( 0 , 1 ).value= int (m[ 0 ]) # 将匹配成功的数据写入第 2 列
ws.cell( 1 , 2 , ' 金额 ' ) # 编写第 2 列标题
wb.save( ' 提取结果 .xlsx' ) # 保存为另外的文件
import re
lst1=re.search( r'\d+' , '120 元 / 千克 - 牛肉 ' )
lst2=re.search( r'\d+' , ' 牛肉 -120 元 / 千克 ' )
print (lst1)
print (lst2)
返回结果
《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
方法及参数说明:
regex.search(string[, pos[, endpos]])
string
必选,被匹配的字符串。
pos
可选,指定起始位置。
endpos 可选,指定结束位置。
1.05 实例应用(提取单价与数量求金额)
统计每种产品的采购金额是多少?效果如图 1-2 中 B 列所示。
图 1-2
代码如下:
import re
pattern=re.compile( r'\d+' )
lst1=pattern.search( '10 斤牛肉 460 元 ' )
lst2=pattern.search( '10 斤牛肉 460 元 ' , 4 , 7 )
print (lst1)
print (lst2)
返回结果
import re , openpyxl
wb=openpyxl.load_workbook( ' 采购表 .xlsx' )
ws=wb.active
pattern=re.compile( r'\d+' )
for val in ws[ 'a:a' ][ 1 :]:
l1=pattern.search(val.value)
l2=pattern.search(val.value , l1.span()[ 1 ])
price= int (l1.group()) # 获取单价
number= int (l2.group()) # 获取数量
val.offset( 0 , 1 ).value=price*number
wb.save( ' 结果 .xlsx' ) 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
1.06 拆分字符串(
split )
Python 中虽然有 split 拆分,但没有正则中的 split 强大、灵活。正则中的 Split 返回的是
列表。
1.06.1 re.split 函数
函数及参数说明:
re.split(pattern, string[, maxsplit=0, flags=0])
pattern 匹配的正则表达式
string
要匹配的字符串。
maxsplit 分隔次数, maxsplit=1 分隔一次,默认为 0 ,不限制次数。
Flags
标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
参见:正则表达式修饰符 - 可选标志
用 pattern 分开 string 。如果在 pattern 中捕获到括号,那么所有的组里的文字也会包含
在列表里。如果 maxsplit 非零,最多进行 maxsplit 次分隔,剩下的字符全部返回到列表的最
后一个元素。
1.06.2 regex.split 方法
方法及参数说明:
regex.split(string, maxsplit=0)
import re
# 常规拆分
lst1=re.split( r'-' , '01 张三 -02 李四 -03 王五 -04 陈小兵 -05 大龙 ' )
# 添加括号拆分
lst2=re.split( r'(-)' , '01 张三 -02 李四 -03 王五 -04 陈小兵 -05 大龙 ' )
# 指定拆分次数
lst3=re.split( r'-' , '01 张三 -02 李四 -03 王五 -04 陈小兵 -05 大龙 ' , 3 )
print (lst1)
print (lst2)
print (lst3)
返回结果
['01 张三 ', '02 李四 ', '03 王五 ', '04 陈小兵 ', '05 大龙 ']
['01 张三 ', '-', '02 李四 ', '-', '03 王五 ', '-', '04 陈小兵 ', '-', '05 大龙 ']
['01 张三 ', '02 李四 ', '03 王五 ', '04 陈小兵 -05 大龙 '] 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
string
要匹配的字符串。
maxsplit 分隔次数, maxsplit=1 分隔一次,默认为 0 ,不限制次数。
1.07 实例应用(整理数据方法 1 )
整理参赛表中的数据,将每个班的参加名单整理成一个规范的表格。如图 1-3 所示。
图 1-3
代码如下所示:
import re
# 常规拆分
pattern1=re.compile( r'-' )
lst1=pattern1.split( '01 张三 -02 李四 -03 王五 -04 陈小兵 -05 大龙 ' )
# 添加括号拆分
pattern2=re.compile( r'(-)' )
lst2=pattern2.split( '01 张三 -02 李四 -03 王五 -04 陈小兵 -05 大龙 ' )
# 指定拆分次数
lst3=pattern1.split( '01 张三 -02 李四 -03 王五 -04 陈小兵 -05 大龙 ' , 3 )
print (lst1)
print (lst2)
print (lst3)
返回结果
['01 张三 ', '02 李四 ', '03 王五 ', '04 陈小兵 ', '05 大龙 ']
['01 张三 ', '-', '02 李四 ', '-', '03 王五 ', '-', '04 陈小兵 ', '-', '05 大龙 ']
['01 张三 ', '02 李四 ', '03 王五 ', '04 陈小兵 -05 大龙 '] 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
1.08 查找字符串 -1 (
findall )
之前的 match,fullmatch,search 只匹配一次,并且返回的是 Match 对象,但 Findall 函数(方
法)返回所有匹配成功的字符串。返回的是列表类型。如果没有找到匹配的,则返回空列表。
Findall 如果没有分组,则直接返回匹配成功的所有字符串;如只有一个分组,则返回分
组中的值到列表;如果多于一个分组,则以元组的方式将每个分组内容返回到列表中。
1.08.1 re.findall 函数
函数及参数说明:
re.findall(pattern,string)
pattern 匹配的正则表达式
string
要匹配的字符串。
flags
标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
参见:正则表达式修饰符 - 可选标志
对 string 返回一个不重复的 pattern 的匹配列表, string 从左到右进行扫描,匹配按找
到的顺序返回。如果样式里存在一到多个组,就返回一个组合列表;就是一个元组的列表(如
果样式里有超过一个组合的话)。空匹配也会包含在结果里。
import re , openpyxl
wb=openpyxl.load_workbook( ' 参赛表 .xlsx' )
ws=wb.active
nwb=openpyxl.Workbook()
nws=nwb.active
pattern = re.compile( '(\d+)' )
nws.append([ ' 班级 ' , ' 学号 ' , ' 姓名 ' ])
for r1 , r2 in ws.iter_rows( 2 ):
lst = pattern.split(r2.value)[ 1 :]
for i in range ( 0 , len (lst) , 2 ):
nws.append([r1.value]+lst[i:i+ 2 ])
nwb.save( ' 结果表 .xlsx' ) 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
1.08.2 regex.findall 方法
方法及参数说明:
regex.findall(string[, pos[, endpos]])
string
待匹配的字符串。
pos
可选参数,指定字符串的起始位置,默认为 0 。
endpos 可选参数,指定字符串的结束位置,默认为字符串的长度。
import re
s= ' 张三 2 李四 3 王五 4 陈小兵 15 大龙 '
# 常规匹配
l1=re.findall( r'\d+\D+' , s)
# 添加一组括号
l2=re.findall( r'(\d+)\D+' , s)
# 添加两组括号
l3=re.findall( r'(\d+)(\D+)' , s)
print (l1)
print (l2)
print (l3)
返回结果
['2 李四 ', '3 王五 ', '4 陈小兵 ', '15 大龙 ']
['2', '3', '4', '15']
[('2', ' 李四 '), ('3', ' 王五 '), ('4', ' 陈小兵 '), ('15', ' 大龙 ')] 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
import re
s= '31 张三 2 李四 3 王五 4 陈小兵 15 大龙 '
# 常规匹配
pattern1=re.compile( r'\d+\D+' )
l1=pattern1.findall(s)
# 添加一组括号
pattern2=re.compile( r'(\d+)\D+' )
l2=pattern2.findall(s)
# 添加多组括号
pattern3=re.compile( r'(\d+)(\D+)' )
l3=pattern3.findall(s)
print (l1)
print (l2)
print (l3)
返回结果
['31 张三 ', '2 李四 ', '3 王五 ', '4 陈小兵 ', '15 大龙 ']
['31', '2', '3', '4', '15']
[('31', ' 张三 '), ('2', ' 李四 '), ('3', ' 王五 '), ('4', ' 陈小兵 '), ('15', ' 大龙 ')]
1.09 实例应用(整理数据方法 2 )
如图 1-4 所示,前面我们整理个参赛表,但希望能再改进一下。
图 1-4
代码如下所示: 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
1.10 查找字符串 -2 ( finditer )
finditer 和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为
一个迭代器返回。迭代器中的每个元素则是 re.Match 对象。
1.10.1 re.finditer
函数及参数说明:
re.finditer(pattern, string, flags=0)
pattern 匹配的正则表达式
string
要匹配的字符串。
flags
标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
参见:正则表达式修饰符 - 可选标志
import re , openpyxl
wb=openpyxl.load_workbook( ' 参赛表 .xlsx' )
ws=wb.active
nwb=openpyxl.Workbook()
nws=nwb.active
pattern = re.compile( '
(\d+)(\D+)' )
nws.append([ ' 班级 ' , ' 学号 ' , ' 姓名 ' ])
for r1 , r2 in ws.iter_rows( 2 ):
lst = pattern.findall(r2.value)
for x in lst:
nws.append((r1.value , )+x)
nwb.save( ' 结果表 .xlsx' ) 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
re.Match[0] ,有无分组均提取匹配成功所有字符串。
re.Match[1] ,有分组,提取分组中的第 1 组的内容。
re.Match[…] ,有分组,提取分组中指定组的内容。
1.10.2 regex.finditer 方法
方法及参数说明:
regex.finditer(string[, pos[, endpos]])
string
待匹配的字符串。
pos
可选参数,指定字符串的起始位置,默认为 0 。
endpos 可选参数,指定字符串的结束位置,默认为字符串的长度。
使用了编译后样式,也可以接收可选参数 pos 和 endpos ,限制搜索范围。并且执行结
果是一个迭代器对象,不占内存空间,匹配速度更快。
import re
s= '31 张三 2 李四 3 王五 4 陈小兵 15 大龙 '
# 常规匹配
l1=re.finditer( r'\d+\D+' , s)
# 添加一组括号
l2=re.finditer( r'\d+(\D+)' , s)
# 添加两组括号
l3=re.finditer( r'(\d+)(\D+)' , s)
print ([i[ 0 ] for i in l1])
print ([(i[ 0 ] , i[ 1 ]) for i in l2])
print ([(i[ 0 ] , i[ 1 ] , i[ 2 ]) for i in l3])
返回结果
['31 张三 ', '2 李四 ', '3 王五 ', '4 陈小兵 ', '15 大龙 ']
[('31 张三 ', ' 张三 '), ('2 李四 ', ' 李四 '), ('3 王五 ', ' 王五 '), ('4 陈小兵 ', ' 陈小兵 '), ('15
大龙 ', ' 大龙 ')]
[('31 张三 ', '31', ' 张三 '), ('2 李四 ', '2', ' 李四 '), ('3 王五 ', '3', ' 王五 '), ('4 陈
小兵 ', '4', ' 陈小兵 '), ('15 大龙 ', '15', ' 大龙 ')] 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
import re
s= '31 张三 2 李四 3 王五 4 陈小兵 15 大龙 '
# 常规匹配
pattern1=re.compile( r'\d+\D+' )
l1=pattern1.finditer(s)
print (l1)
# 添加一组括号
pattern2=re.compile( r'(\d+)\D+' )
l2=pattern2.finditer(s)
# 添加两组括号
pattern3=re.compile( r'(\d+)(\D+)' )
l3=pattern3.finditer(s)
print ([i[ 0 ] for i in l1])
print ([(i[ 0 ] , i[ 1 ]) for i in l2])
print ([(i[ 0 ] , i[ 1 ] , i[ 2 ]) for i in l3])
返回结果
['31 张三 ', '2 李四 ', '3 王五 ', '4 陈小兵 ', '15 大龙 ']
[('31 张三 ', '31'), ('2 李四 ', '2'), ('3 王五 ', '3'), ('4 陈小兵 ', '4'), ('15
大龙 ', '15')]
[('31 张三 ', '31', ' 张三 '), ('2 李四 ', '2', ' 李四 '), ('3 王五 ', '3', ' 王五 '),
('4 陈小兵 ', '4', ' 陈小兵 '), ('15 大龙 ', '15', ' 大龙 ')]
1.11 实例应用(表格数据整理)
如图 1-5 所示,将数据转换成规范的表格。
图 1-5 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
代码如下:
1.12 Sub 函数与方法
可以对匹配成功的字符串进行替换处理。
1.12.1 re.sub 函数
函数及参数说明:
re.sub(pattern, repl, string, count=0, flags=0)
pattern 正则中的模式字符串。
repl
替换的字符串,也可为一个函数。
string
要被查找替换的原始字符串。
count
模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
flags
编译时用的匹配模式,数字形式。
第二参数为字符串的查找替换
第二参数为函数的查找替换
import re , openpyxl
pattern=re.compile( r'(\d+)(\D+)' )
wb=openpyxl.load_workbook( ' 捐款表 .xlsx' )
ws=wb.active
nws=wb.create_sheet( ' 结果 ' )
nws.append([ ' 公司名 ' , ' 姓名 ' , ' 金额 ' ])
for v in ws[ 'a:a' ][ 1 :]:
s=v.value.split( '-' )
i=pattern.finditer(v.value , len (s[ 0 ]))
l=[[s[ 0 ] , m[ 2 ] , int (m[ 1 ])] for m in i]
for l1 in l:
nws.append(l1)
wb.save( ' 整理结果 .xlsx' )
import re
s1=re.sub( r'\d+' , ' 、 ' , ' 张三平 2800 李四 7054 林森 11200' )
print (s1)
返回结果
张三平、李四、林森、 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
1.12.2 Regex.sub 方法
方法及参数说明:
regex.sub(repl, string, count=0)
repl
替换的字符串,也可为一个函数。
string
要被查找替换的原始字符串。
count
模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
第一参数是为字符串时的查找替换
第一参数是为函数时的查找替换
import re
# --------- 自定义函数 ----------
def fun (m):
return m[0] + ' 、 '
#-----------------------------
s1=re.sub( r'\d+' , fun , ' 张三平 2800 李四 7054 林森 11200' )
print (s1)
返回结果
张三平 2800 、李四 7054 、林森 11200 、
import re
pattern=re.compile( r'\d+' )
s1=pattern.sub( ' 、 ' , ' 张三平 2800 李四 7054 林森 11200' )
print (s1)
返回结果
张三平、李四、林森、 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
import re
pattern=re.compile( r'\d+' )
# --------- 自定义函数 ----------
def fun (m):
return '(' +m[0]+ ') 、 '
#-----------------------------
s1=pattern.sub(fun , ' 张三平 2800 李四 7054 林森 11200' )
print (s1)
返回结果
张三平 (2800) 、李四 (7054) 、林森 (11200) 、
还有一种 subn 的方式,则是增加了查找替换成功的次数,与结果组合成一个元组。
1.13 实例应用(判断字符串中的数字)
如图 1-6 所示,判断 B 列的分数,如果大于等于 90 分,则显示为“优秀”,否则显示为
“普通”。
图 1-6
代码如下所示: 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
第 2 章 正则表达式元字符详解
在第 1 章中讲解了,
Python 中正则表达式的常用函数和方法,这对数据的处理非常有用。
但还有最重要的一项技术(正则表达式字符)没有讲解,使得这些函数和方法还不能完全发
挥作用。本章将系统讲解这一内容。
2.01 元字符之单个字符(字母、数字、任意)
实例
描述
使用 re.ASCII 或 re.A 属性,
内联标志为 ?a
让 \w, \W, \b, \B, \d, \D, \s
和 \S 只匹配 ASCII ,而不是
Unicode 。
\
转义,将普通字符与特殊字符的互转。
\d
匹配一个数字字符。等价于 [0-9] 。
\D
匹配一个非数字字符。等价于 [^0-9] 。
\w
匹配 Unicode 字符 、 数字 及 下划线 。
\W
匹配 Unicode 中非包括下划线的任何字符。
\s
匹配任何空白字符,包括空格、制表符、换页符
等等。等价于 [ \f\n\r\t\v] 。
\S
匹配任何非空白字符。等价于 [^ \f\n\r\t\v] 。
.
匹 配 任 意 字 符 , 除 了 换 行 符 \n , 当
re.DOTALL\re.S\(?s) 标记被指定时,则可以匹配包
括换行符的任意字符。
2.02 实例应用(单词整理)
如图 2-1 所示,统计 txt 演讲稿中,每个单词出现的频次。
import re , openpyxl
wb=openpyxl.load_workbook( ' 成绩表 .xlsx' )
ws=wb.active
pattern=re.compile( r'\d+' )
# --------------------------------------
def fun (m):
n= int (m[ 0 ])
level= '( 优秀 )' if n>= 90 else '( 普通 )'
return m[ 0 ]+level
# --------------------------------------
for c in ws[ 'b:b' ][ 1 :]:
c.value=pattern.sub(fun , c.value)
wb.save( ' 成绩表 -1.xlsx' ) 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
图 2-1
代码如下:
2.03 元字符之单个字符(字符组)
字符组 [ … ] 可以是一段字符范围,或单个字符的指定。下面举例说明:
代码
含义
[0-9] 、 [1-59]
所有单个数字、 1 到 5 或者 9
[A-Za-z] 、 [A-z] 、 [d-mz4-8] 所有字母、所有字母、字母 d 到 m 数字 4 到 8
[ 一 - 龥 ] [\u4e00-\u9fa5]
汉字范围。
[\d\w]
可以将元字符放在里面。
[^ …… ]
匹配输入字符串的开始位置,除非在方括号表达式中使用,此
import re , openpyxl
wb=openpyxl.Workbook() # 新建工作簿
ws=wb.active # 获取工作表对象
pattern=re.compile( r'\w+' , re.A)
dic={}
with open ( ' 演讲稿 .txt' , 'r' ) as f: # 读取 txt 文件
m=f.read()
for w in pattern.findall(m): # 将拆分出的单词进行统计
if w in dic.keys():
dic[w]+= 1
else :
dic[w]= 1
l= sorted (dic.items() , key = lambda x:x[ 1 ] , reverse = 1 ) # 排序处理
for v in l:
ws.append(v) # 写入工作表
wb.save( ' 统计结果 .xlsx' ) 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 \^ 。
|
或关系,可以单字符的或关系,也可以表达式的或关系。
2.04 实例应用(统计达标的科目数)
如图 2-2 所示,统计 B 列中分数大于等于 80 以上的科目数有多少?
图 2-2
代码如下所示:
2.05 元字符之计数功能(长度表示)
前面两种我们把各种数符的表示方法基本学习完成,但都只能表示一个字符。本小节学
习如何对字符长度的控制。有些地方也叫量词。
字符
描述
{n}
n 是一个非负整数。匹配确定的 n 次。例如, 'o{2}' 不能匹配 "Bob" 中的 'o' ,
但是能匹配 "food" 中的两个 o 。
{n,}
n 是一个非负整数。至少匹配 n 次。例如, 'o{2,}' 不能匹配 "Bob" 中的 'o' ,但
能匹配 "foooood" 中的所有 o 。 'o{1,}' 等价于 'o+' 。 'o{0,}' 则等价于 'o*' 。
{n,m}
m 和 n 均为非负整数,其中 n <= m 。最少匹配 n 次且最多匹配 m 次。例如,
"o{1,3}" 将匹配 "fooooood" 中的前三个 o 。 'o{0,1}' 等价于 'o?' 。请注意在逗号
和两个数之间不能有空格。
*
匹配前面的子表达式零次或多次。例如, zo* 能匹配 "z" 以及 "zoo" 。 * 等价于
{0,} 。
+
匹配前面的子表达式一次或多次。例如, 'zo+' 能匹配 "zo" 以及 "zoo" ,但不能
匹配 "z" 。 + 等价于 {1,} 。
?
匹配前面的子表达式零次或一次。例如, "do(es)?" 可以匹配 "do" 、 "does" 中
import re , openpyxl
wb=openpyxl.load_workbook( ' 成绩表 .xlsx' )
ws=wb.active
pattern=re.compile( '[89]\d|100' )
for v in ws[ 'b:b' ][ 1 :]:
v.offset( 0 , 1 ).value= len (pattern.findall(v.value))
wb.save( ' 结果 .xlsx' ) 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
的 "does" 、 "doxy" 中的 "do" 。 ? 等价于 {0,1} 。
2.06 实例应用(提取数据重构表格)
如图 2-3 的示,提取姓名,并根据身份证号再提取年龄和性别,形成一个规范的表格。
图 2-3
代码如下所示:
2.07 元字符之位置匹配符(单词边界、开头结尾)
字符
描述
\b
匹配一个单词边界,即字与空格间的位置。
\B
非单词边界匹配。
\A
指定匹配必须出现在字符串的开头(忽略 re.M 选项)。
\Z
指定匹配必须出现在字符串的结尾(忽略 re.M 选项)。
^
匹配输入字符串开始的位置。设置 re.M 后,支持多行。
$
匹配输入字符串结尾的位置。设置 re.M 后,支持多行。
2.08 实例应用(统计以 26 个字母开头的单词个数)
import re , openpyxl , datetime
wb=openpyxl.load_workbook( ' 名单表 .xlsx' )
ws=wb.active
nws=wb.create_sheet( ' 整理结果 ' )
nws.append([ ' 姓名 ' , ' 年龄 ' , ' 性别 ' ])
td=datetime.date.today().year
pattern=re.compile( '([^\w]+)\d{6}(\d{4})\d{6}(\d)\d' , re.A)
for v in ws[ 'a:a' ]:
l=pattern.findall(v.value)[ 0 ]
nws.append((l[ 0 ] , td- int (l[ 1 ]) , ' 男 ' if int (l[ 2 ])% 2 else ' 女 ' ))
wb.save( ' 整理结果 .xlsx' ) 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
如图 2-4 所示,统计演讲稿中以 26 个字母开头的音词个数。
图 2-4
代码如下所示:
2.09 分组捕获
2.09.1 普通分组
分组,就是希望对正则表达式字符串中的某一部分当作整体看待,便于表示,如果要提
取分组中的数据,也更方便。
2.09.1 命名分组
命名分组是 python 正则中的一种特殊的分组方式,它可对分组进行命名,从而在引用时
可以不同序号方式引用,而用命称来引用。命名组很有用,因为它们允许你使用容易记住的
名称,而不必记住数字。
分组命名格式为:在分组的左括号后面加 ?P< 名称 > ,注意 P 字母是大写的。然后,后面
是正常的正则字符编写。
import re , openpyxl
wb=openpyxl.Workbook()
ws=wb.active
ws.append([ ' 字母 ' , ' 数量 ' ])
with open ( ' 演讲稿 .txt' , 'r' ) as f: # 读取 txt 文件
m=f.read()
for i in range ( 65 , 91 ):
p=re.findall( r'\b' + chr (i)+ r'\w+\b' , m , re.A|re.I)
ws.append([ chr (i) , len (p)])
wb.save( ' 统计结果 .xlsx' ) 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
2.09.2 分组元素的提取
如果要提取分组中的值,可以使用 match 、 search 、 finditer 、 findall 等函数,如果要出现
多次匹配,则只能使用 findall 或 finditer ,
findall 只能获取分组内容,而 finditer 返回是迭代器,
循环出来的是 re.match 对象,可以获取更多匹配信息。分组中的信息可以用 re.Match[ 索引 ]
或 re.Match[ 分组名 ] 的方式提取。
2.10 实例应用(对字符串中的分数进行统计和排序)
如图 2-5 所示,每个人的分数是零乱的,如果需要对分数进行排序并统计科目数。
图 2-5
代码如下所示:
import re
print (re.findall( r'(\d+)( ?P [A-z]+)([ 一 - 龥 ]+)' , '985Jack 我来了 ' ))
返回结果
[('985', 'Jack', ' 我来了 ')]
import re , openpyxl
wb=openpyxl.load_workbook( ' 分数表 .xlsx' )
ws=wb.active
def fun (x):
l1=x[ 2 ].split( ' 、 ' )
l2= sorted (l1 , key = int , reverse = True )
s= ' 、 ' .join(l2)
return x[ 1 ]+s+ '( 共 %d 科 )' % len (l1)
for v in ws[ 'a:a' ]:
p2=re.sub( r'([ 一 - 龥 ]+)([\d 、 ]+)' , fun , v.value)
v.offset( 0 , 1 ).value=p2
wb.save( ' 处理结果 .xlsx' ) 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
2.11 分组引用
分组优点很多,可以直接在正则字符串中表示,也可以在正则字符串的再次引用。其次,
除了在 re.Match 中获取引用,也可以在替换函数中引用使用。
2.11.1 分组在正则中的引用
案例 1 :叠字识别。
import re
s= ' 我们欢欢喜喜的来到了公园,蹦蹦跳跳的 '
p2=re.finditer( r'([ 一 - 龥 ])\1([ 一 - 龥 ])\2' , s)
print ([i[ 0 ] for i in p2])
返回结果
[' 欢欢喜喜 ', ' 蹦蹦跳跳 ']
案例 2 :叠词识别。
import re
s= ' 先巴拉巴拉,再收敛收敛,就行了。 '
p2=re.finditer( r'([ 一 - 龥 ]{2})\1' , s)
print ([i[ 0 ] for i in p2])
返回结果
[' 巴拉巴拉 ', ' 收敛收敛 ']
如果是命名分组,要获取
import re
s= ' 先巴拉巴拉,再收敛收敛,就行了。 '
p2=re.finditer( r'( ?P [ 一 - 龥 ]{2})( ?P=n )' , s)
print ([i[ 0 ] for i in p2])
返回结果
[' 巴拉巴拉 ', ' 收敛收敛 ']
2.11.2 分组在 sub 中的应用
在使用 sub 在替换时,也可以引用分组中的内容,可以使用 \1 、 \g<1> 、 \g 三种方
法引用。 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
import re
s= '85 张三 100 李四平 98 王大花 74 刘生 '
p1=re.sub( r'(\d+)([ 一 - 龥 ]+)' , r'\2\1 、 ' , s)
p2=re.sub( r'(\d+)([ 一 - 龥 ]+)' , r'\g<2>\g<1> 、 ' , s)
p3=re.sub( r'(?P\d+)(?P[ 一 -
龥 ]+)' , r'\g\g 、 ' , s)
print (p1)
print (p2)
print (p3)
返回结果
张三 85 、李四平 100 、王大花 98 、刘生 74 、
2.11.3 分组顺序
如果有很多分组,甚至有嵌套,那么如何匹配组号呢,其实很基础,数左括号就可以,
第几个左括号,就是第几组。
import re
target = 'tree/combined 010-12345'
pattern = r'(([^/]*)(/.*)?)[\s]+((\d{3})\-(\d{3,8})$)' # [^] :匹配
除了里面列出的任一字符
m = re.findall(pattern , target)
print (m)
返回结果
[('tree/combined', 'tree', '/combined', '010-12345', '010', '12345')]
2.12 实例应用(汇总文本中的商品金额)
如图 2-6 所示,计算每个订单的消费总金额。对 C 列中各商品的金额进行求和。 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
图 2-6
代码如下所示:
import re , openpyxl
wb=openpyxl.load_workbook( ' 餐表 .xlsx' )
ws=wb.active
l=ws[ 'c:c' ][ 1 :]
pattern=re.compile( r' ¥ (\d+\.\d+)' )
for v in l:
sumval= sum ([ float (i) for i in pattern.findall(v.value)])
v.offset( 0 , 1 ).value=sumval
wb.save( ' 统计结果 .xlsx' )
2.13 分组选择匹配
(?(id/name)yes-pattern|no-pattern) ,如果给定的 id 或 name 存在,将会尝试匹配
yes-pattern ,否则就尝试匹配 no-pattern , no-pattern 可选,也可以被忽略。
1. 分组 1 是有 < ,结尾一定有 > 。
import re
s= ' 曾贤志 Jack>; 张三 李明 '
i=re.finditer( r'(<)?[A-z]+(?(1)>)' , s)
for m in i:
print (m[ 0 ])
返回结果
Jack
Bob
2. 分组 1 是数字,结尾一定是数字。否则,结尾就是汉字。 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
import re
l=[ '42luccs450' , 'Jack 张三 ' , 'Lily599' , '9Bob95' , 'Lucy 李萌萌 ' , '6Na' ]
for s in l:
m=re.search( r'(\d+)?[A-z]+(?(1)\d+|[ 一 - 龥 ]+)' , s)
if m!= None :
print (m[ 0 ])
返回结果
42luccs450
Jack 张三
9Bob95
Lucy 李萌萌
2.14 实例应用(按条件筛选金额)
如图 2-7 所示,将金额列中的整数,或者小数点两位以前的金额筛选出来。
图 2-7
代码如下所示: 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
2.15 非分组捕获
(?…) ,这是个扩展标记法。 '?' 后面的第一个字符决定了这个构建采用什么样的语法。这
种扩展通常并不创建新的分组, (?P...) 命名分组是唯一的例外。
本节学习使用了 ? ,但不具有分组捕获的功能。
2.15.1 内联标记
编译标志允许你修改正则表达式的工作方式。
(?aimsx) , ( 'a', 'i', 'm', 's', 'x' 中的一个或多个 ) 这个组合匹配一个空字符串,这个方法就很
有用,免去了在 re.compile() 中传递 flag 参数。 标记应该在表达式字符串首位表示。
re.A
re.ASCII
(?a)
让 \w, \W, \b, \B, \d, \D, \s 和 \S 只匹配 ASCII ,而不是 Unicode 。这只对
Unicode 样式有效,会被 byte 样式忽略。相当于前面语法中的内联标志
(?a) 。
ire.I
re.IGNORECASE
(?i)
进行忽略大小写匹配;表达式如 [A-Z] 也会匹配小写字符。 Unicode 匹配
(比如 Ü 匹配 ü)同样有用,除非设置了 re.ASCII 标记来禁用非 ASCII
匹配。当前语言区域不会改变这个标记,除非设置了 re.LOCALE 标记。
这个相当于内联标记 (?i) 。
re.M
re.MULTILINE
(?m)
设置以后,样式字符 '^' 匹配字符串的开始,和每一行的开始(换行符后
面紧跟的符号);样式字符 '$' 匹配字符串尾,和每一行的结尾(换行符
前面那个符号)。默认情况下,’ ^ ’ 匹配字符串头, '$' 匹配字符串尾。
对应内联标记 (?m) 。
re.S
re.DOTALL
(?s)
让 '.' 特殊字符匹配任何字符,包括换行符;如果没有这个标记, '.' 就匹
配 除了 换行符的其他任意字符。对应内联标记 (?s) 。
re.X
re.VERBOSE
这个标记允许你编写更具可读性更友好的正则表达式。通过分段和添加注
释。空白符号会被忽略,除非在一个字符集合当中或者由反斜杠转义,或
import re , openpyxl
wb=openpyxl.load_workbook( ' 金额表 .xlsx' )
ws=wb.active
nws=wb.create_sheet( ' 筛选结果 ' )
n= 0
nws.append([ ' 序号 ' , ' 产品 ' , ' 金额 ' ])
for v in ws[ 'b:b' ]:
m = re.search( r'^\d+(\.)?(?(1)\d{1,2})$' , v.value)
if m != None :
n+= 1
nws.append([ '%02d' %n , v.offset( 0 , - 1 ).value , m[ 0 ]])
wb.save( ' 筛选结果 .xlsx' ) 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
(?x)
者在 *?, (?: or (?P< … > 分组之内。当一个行内有 # 不在字符集和转义序
列,那么它之后的所有字符都是注释。对应内联标记 (?x) 。
内联标记演示 1
内联标记演示 2
2.15.2 注释
(?#…)
注释;里面的内容会被忽略。
2.15.3 非分组
import re
p=re.findall( r'(?im)^[A-Z ]+$' , 'Who am I \n Are you Ok' )
print (p)
返回结果
['Who am I', 'Are you Ok']
import re
s= 'Jack99 \n Lucass100 \n Bob85 \n 88Lily86'
print (re.findall( r'''
(?imx) # 编译标志
^ # 开头为
[A-Z]+ # 配置更多的字母
\d+ # 配置更多的数字
$ # 结尾
''' , s))
返回结果
['Jack99', 'Lucass100', 'Bob85']
import re
s= 'Jack99 \n Lucass100 \n Bob85 \n 88Lily86'
print (re.findall( r'(?i)(?# 内联标记 )[a-z]+(?# 提取姓名 )' , s))
返回结果
['Jack', 'Lucass', 'Bob', 'Lily'] 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
(?:…) 正则括号的非捕获版本。匹配在括号内的任何正则表达式,但该分组所匹配的子字
符串不能在执行匹配后被获取或是之后在模式中被引用。主要应用需要分组,但又不需要捕
获分组内容时,因为捕获分组还是要占用内存空间的。
import re
pattern=re.compile( r'(?: 成都 | 重庆 )\d+' )
p=pattern.findall( ' 北京 987 成都 101 上海 780 重庆 67' )
print (p)
返回结果
[' 成都 101', ' 重庆 67']
2.16 实例应用(多条件提取数据汇总)
要求:求长春和上海公司的管理部、人事部、销售部的总金额
方法 1
import re , openpyxl
wb=openpyxl.load_workbook( ' 信息表 .xlsx' )
ws=wb.active
pattern=re.compile( r' (?: 长春 | 上海 ).*-\D+(\d+) ( (?: 管理部 | 人事部 | 销售部 ) ' )
l=[]
for v in ws[ 'a:a' ]:
l+=pattern.findall(v.value)
print ( sum ([ int (i) for i in l]))
方法 2
import re , openpyxl
wb=openpyxl.load_workbook( ' 信息表 .xlsx' )
ws=wb.active
s= 0
pattern=re.compile( r' (?: 长春 | 上海 ).*-\D+(\d+) ( (?: 管理部 | 人事部 | 销售部 ) ' )
for v in ws[ 'a:a' ]:
p=pattern.search(v.value)
if p!= None :
s+= int (p[ 1 ])
print (s)
2.17 零宽断言 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
在使用正则表达式时,有时需要捕获的内容前后必须是特定内容,但又不捕获这些特定
内容的时候,这时则使用零宽断言。有的叫 " 环视 " 或者 " 预搜索 " 等。
零宽断言正如它的名字一样,是一种零宽度的匹配,它匹配到的内容不会保存到匹配结
果中去,最终匹配结果只是一个位置而已。作用是给指定位置添加一个限定条件,用来规定
此位置之前或者之后的字符必须满足限定条件才能使正则中的字表达式匹配成功。
表达式
说明
(?=exp)
它断言此位置后面匹配表达式 exp
(?!exp)
它断言此位置后面不匹配表达式 exp
(?<=exp)
它断言此位置前面匹配表达式 exp
反向断言不支持匹配
不定长的表达式
(?
它断言此位置前面不匹配表达式 exp
(?=exp) 零宽正向先行断言 (zero-width positive lookahead assertion)
(?!exp) 零宽负向先行断言 (zero-width negative lookahead assertion)
(?<=exp) 零宽正向后行断言 (zero-width positive lookbehind assertion)
(? 零宽负向后行断言 (zero-width negative lookbehind assertion)
例如:给数字添加分隔线
import re
pattern= re.compile( r'[ 一 - 龥 ]+(?=\d+)' )
print (pattern.findall( ' 张三 100, 李四 85, 王五 79, 麻子 Job, 小明 ' ))
pattern= re.compile( r'[ 一 - 龥 ]+(?!\d+)' )
print (pattern.findall( ' 张三 100, 李四 85, 王五 79, 麻子 Job, 小明 ' ))
pattern= re.compile( r'(?<=[ 一 - 龥 ])\d+' )
print (pattern.findall( ' 张三 100, 李四 85, 王五 79, 麻子 Job, 小明 ' ))
pattern= re.compile( r'(? 一 - 龥 ])\d+' )
print (pattern.findall( ' 张三 100, 李四 85, 王五 79, 麻子 Job, 小明 ' ))
返回结果
[' 张三 ', ' 李四 ', ' 王五 ']
[' 张 ', ' 李 ', ' 王 ', ' 麻子 ', ' 小明 ']
['100', '85', '79']
['00', '5', '9'] 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
import re
print (re.sub( r'(?=\d)' , r'-' , ' 张三 9527' ))
print (re.sub( r'(?<=\d)' , r'-' , ' 张三 9527' ))
print (re.sub( r'(?<=\d)(\d)' , r'-\1' , ' 张三 9527' ))
print (re.sub( r'(? , r'-\1' , ' 张三 9527' ))
print (re.sub( r'(\d)(?=\d)' , r'\1-' , ' 张三 9527' ))
print (re.sub( r'(\d)(?!$)' , r'\1-' , ' 张三 9527' ))
返回结果
张三 -9-5-2-7
张三 9-5-2-7-
张三 9-5-2-7
张三 9-5-2-7
张三 9-5-2-7
张三 9-5-2-7
2.18 实例应用(将考号规范化)
如图 2-8 所示,将括号中的考号规范成四位数。
图 2-8
代码如下:
import re , openpyxl
wb=openpyxl.load_workbook( ' 晋级表 .xlsx' )
ws=wb.active
def fun (m):
return '%04d' % int (m[ 0 ])
pattern= re.compile( r'(?<= ( )\d{1,3}(?= ) )' )
for v in ws[ 'b:b' ][ 1 :]:
v.value=pattern.sub(fun , v.value)
wb.save( ' 处理结果 .xlsx' )
2.19 贪婪与非贪婪(惰性) 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
贪婪:能匹配 多 少就 多 少。
非贪婪:能匹配多 少 就多 少 。
量词默认是贪婪模式;在量词后面直接加上一个问号?就是非贪婪模式。
非贪婪类型
注释
*?
重复任意次,但尽可能少重复
+?
重复 1 次或更多次,但尽可能少重复
??
重复 0 次或 1 次,但尽可能少重复
{n,m}?
重复 n 到 m 次,但尽可能少重复
{n,}?
重复 n 次以上,但尽可能少重复
示例如下:
2.20 实例应用(整理零乱的员工信息)
图 2-9
import re
p=re.findall( r'.+?(?=\d)' , '1. 四川大学 2. 石河子大学 3. 东南大学 ' )
for i in p:
print (i)
返回结果
1. 四川大学
2. 石河子大学 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
图 2-10
2.21 re.match 对象的方法与属性
可以返回 re.match 对像的方法 ( 函数 ) 有 match,fullmatch,search,finditer 。下面就讲讲
re.match 对象有哪些方法和属性。
方法或属性
注释
string
要被匹配的字符串。
re
正则表达式对象。
lastgroup
返回最后一个分组的组名字,没有产生匹配返回 None 。
lastindex
捕获组的最后分组索引值,相当于计算组数,没有分组则返回 None 。
endpos
定位被匹配字符串的终点位置,可以看做字符串长度。
pos
定位被匹配字符串的起点位置,默认是 0 ,用户如果重新指定位置,
则该属性则会随之改变。
import re , openpyxl
wb=openpyxl.Workbook()
ws=wb.active
with open ( ' 员工信息 .txt' , 'r' ) as f: # 读取 txt 文件
m=f.read()
p=re.findall( r'([ 一 - 龥 ]+) (\w{18}) ([ 男女 ]) (\d+) ([\w ]+?) (?=[ 一 -
龥 ]+ \d)' , m+ ' 一 1' )
ws.append([ ' 姓名 ' , ' 身份证号 ' , ' 性别 ' , ' 年龄 ' , ' 籍贯 ' ])
for t in p:
ws.append(t)
wb.save( ' 整理结果 .xlsx' ) 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
span([group])
返回匹配成功的字符串位置,返回一个二元组 ( 起始 , 终止 ) , span()
和 span(0) 表示整个匹配的起止位置。
也可返回指定分组的起止位置。如 span(2) 表示返回第 2 个分组的起
止位置。
start([group])
end([group])
返回匹配成功字符串起始和结束位置,相当于对 span 的拆分,表示
方式与 span 相同。
group([group1, ...])
返回匹配成功的所有字符串,如有分组,也可以返回指定分组中的
内容。如 group() 和 group(0) 表示返回全部, group(1,2) 表示返回第 1 、
第个分组的内容。如果有命名分组,也可以用 group('number','name')
groups(default=None)
返回一个元组,包含所有匹配的子组。如果有分组没有参与匹配,
则默认返回 None 。
groupdict(default=None) 返回一个字典,只包含所有的命名分组。 key 就是组名。如果有分
组没有参与匹配,则默认返回 None 。
__getitem__(g)
该方法与 group 表示方式相同,但不能同时返回多个分组内容。与
之前讲解的 re.match[ 索引 ] 用法相同。
expand(template)
将匹配到的分组内容代入 template 中,然后返回。是相当于分组中
的内容格式化。 template 中可以使用 \id 或 \g 、 \g 引用分组,但不能
使用编号 0 。 \id 与 \g 是等价的;但 \10 将被认为是第 10 个分组,如
果你想表达 \1 之后是字符’ 0 ’,只能使用 \g<1>0 。 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
第 3 章 综合应用
3.01 实际案例:提取指定数据到新表
数据源
完成效果:
代码: 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
import re,openpyxl
wb=openpyxl.load_workbook('test.xlsx')
ws=wb['Sheet1']
for cell in ws['E'][1:]:
mat=re.findall('( 第 \d+ 段 ) 压裂施工 .+? 入井液量
(\d+(?:\.\d+)?)m3.+? 本层加砂量 (\d+(?:\.\d+)?)m3',cell.value)
for val in mat:
wb[' 提取结果 '].append((cell.offset(0,-2).value,)+val)
wb.save('test2.xlsx')
3.02 实际案例:汇总提取的数据
数据源 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
完成效果
代码: 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
import re,openpyxl
wb=openpyxl.load_workbook('test.xlsx')
ws=wb.active
dic={}
for cell in ws['B']:
mat=re.findall('([ 一 - 龥 ]+)(\d+) 人 ',cell.value)
for val in mat:
if not val[0] in dic.keys():
dic[val[0]]=int(val[1])
else:
dic[val[0]] +=int(val[1])
nwb=openpyxl.Workbook()
nwb.active.append([' 工种 ',' 人数 '])
for key,item in dic.items():
nwb.active.append([key,item])
nwb.save(' 统计结果 .xlsx')
3.03 实际案例:规范时间数据
将下面不规范时间整理成时间规范时间。
代码 《用 Python 处理 Excel 数据之正则表达式视频教程》 曾贤志
import re,openpyxl
wb=openpyxl.load_workbook(r'test.xlsx')
ws=wb.active
for cell in ws['A'][1:]:
mat=re.match(r'(?:(\d+) 小 ? 时 )?(?:(\d+) 分钟 ?)?(?:(\d+) 秒
钟 ?)?',cell.value)
time=[int(t) for t in mat.groups(0)]
ftime='{:02}:{:02}:{:02}'.format(*time)
cell.offset(0,1).value=ftime
wb.save('test.xlsx')