re模块
re是python内建模块,主要用于处理正则表达式,匹配字符串等工作。
使用正则表达式的步骤
- 导入re
- 分析要处理的字符串,提取其特点
- 用正则表达式来表示提取模式
- 编译模式
- 匹配目标字符串
- 从匹配对象中提取已命名的分组
第一个简单的实验
比如,我们有一个字符串"kumquat: 2 cups",我们希望将其中的‘kumquat’,‘2’,‘cups’提取出来。
按照上面的步骤进行操作。
1导入就不说了
说说2字符串特点,看起来像食谱,冒号左侧是原料,冒号右侧是数量+单位。
3.构造提取模式
(material): (amount) (unit)
pattern = r'(?P\w+):\s(?P\d+)\s+(?P\w+)'
首先,这是一个raw字符串,由于正则大量使用了‘\’,所以使用raw字符串可防止转义。
然后用()进行分组,其中?P
紧接着\w,匹配数字/字母/下划线。+,表示至少匹配一个。另外两组同理。
再说一下冒号,在正则表达式中冒号匹配其自身。
4.编译模式
pattern = r'(?P\w+):\s(?P\d+)\s+(?P\w+)'
pattern = re.compile(pattern_text)
5.匹配目标字符串
通过编译后的匹配模式,来查找目标字符串。
text = "Kumquat: 2 cups"
pattern_match = pattern.match(text)
- 查看匹配结果
可以刚刚在匹配模式中定义的名字取出各组所匹配到的内容,就像从字典中取值一样。
# 分别显示每个组
key_name = pattern_match.group('key_name')
amount = pattern_match.group('amount')
unit = pattern_match.group('unit')
print(key_name, amount, unit)
完整的代码如下
import re
text = "Kumquat: 2 cups"
pattern_text = r"(?P\w+):\s+(?P\d+)\s+(?P\w+)"
pattern = re.compile(pattern_text)
pattern_match = pattern.match(text)
# 分别显示每个组
key_name = pattern_match.group('key_name')
amount = pattern_match.group('amount')
unit = pattern_match.group('unit')
print(key_name, amount, unit)
举几个例子
1. 匹配时间字符串
我们的目标是,从给定的时间字符串中取出符合规则的部分,规则是ISO 8601格式:"YYYY-mm-dd HH:MM:SS".
但是还要兼容另外两种格式。"YYYY-mm-dd HH:MM" 和 "YYYY-mm-dd"。
实际上还兼容"YYYY-mm-dd_HH-MM-SS",等等。
import re
# 判断日期字符串是否符合格式
def check_datetime(dt:str) -> str:
dt_pattern = r"(\d{4}[-_]\d{1,2}[-_]\d{1,2}[\s\w]{1}\d{2}[:_]\d{2}[:_]\d{2})|"\
r"(\d{4}[-_]\d{1,2}[-_]\d{1,2}\s{1}\d{2}[:_]\d{2})|" \
r"(\d{4}[-_]\d{1,2}[-_]\d{1,2})"
comp = re.compile(dt_pattern)
search_result = comp.search(dt)
if search_result:
print(search_result.group(0), search_result.group(1), search_result.group(2), search_result.group(3))
else:
print("nothing finded.")
return dt
dt1 = "2019-02-10 04:06:00"
dt2 = "2019-02-10---"
dt3 = "2019-02-10 04:06"
dt4 = "2019-2-1 04:06:00"
dt5 = "2019-02-01_04:06:00"
dt6 = "2019-02-01_04-06-00"
dt7 = "4565-12-5894894"
res_dt = check_datetime(dt7)
这里列了三个组,它们之间是“或”的关系。
2. 优化一下上面的例子
我们发现dt7也可以匹配到“4565-12-58”,因为我们仅做了位数的匹配,让我们一起修改一下。
看一下年份匹配的地方。
是的,我们不应该匹配4位整数,而是应该由20开头,再匹配两位数字。
import re
# 判断日期字符串是否符合格式
def check_datetime(dt:str) -> str:
dt_pattern = r"(20\d{2}[-_]\d{1,2}[-_]\d{1,2}[\s\w]{1}\d{2}[:_]\d{2}[:_]\d{2})|"\
r"(20\d{2}[-_]\d{1,2}[-_]\d{1,2}\s{1}\d{2}[:_]\d{2})|" \
r"(20\d{2}[-_]\d{1,2}[-_]\d{1,2})"
comp = re.compile(dt_pattern)
search_result = comp.search(dt)
if search_result:
print(search_result.group(0), search_result.group(1), search_result.group(2), search_result.group(3))
else:
print("nothing finded.")
return dt
然后在匹配dt7的时候,就会打印"nothing finded."。