00 需求描述
我们想要从一篇文章/一个段落中,找到包含指定关键词的一个句子,这个句子以逗号或者句号开头,以逗号或者句号结尾。我们来看一个例子:
XXX第四五七医院,创建于1950年12月。位于武汉市江岸区工农兵路15号,占地15万平方米。
是一所集医疗、预防、保健、康复、急救为一体的绿化园林式的综合性XX医院。
我们想要找出这个医院占地面积的数据,因此需要找出包含有关键词占地
的句子,即:
占地15万平方米
正则匹配可以实现以上需求:
import re
restr = 'XXX第四五七医院,创建于1950年12月。位于武汉市江岸区工农兵路15号,占地15万平方米。'
pattern = re.compile('[,。][^,。]*占地[^,。]*[,。]')
search = re.search(restr)
print(search)
# 结果
# ,占地15万平方米。
01 匹配思路
我们要匹配的这个句子,以逗号或者句号开头,也以逗号或者句号结尾,因此选择匹配字符集[]
来做正则表达式的开头和结尾;需要检测的关键词也应该成为正则表达式的一部分;关键词前后可能还有别的字符串,需要采用重复匹配
来实现, 但由于我们需要匹配出的只是包含了两个逗号或者两个句号或者一个逗号一个句号的字符串,我们要在重复匹配中去除多余的逗号或者句号,可以使用字符集求反
实现:
# 1. 匹配开头和结尾的逗号、句号
pattern = re.compile('[,。][,。]')
# 2. 匹配关键字
pattern = re.compile('[,。]占地[,。]')
# 3. 匹配关键词前后的其他字符串
pattern = re.compile('[,。][^,。]*占地[^,。]*[,。]')
# []:选择字符集中的一个
# [^]:字符集取反,除了该括号内的字符
# *:重复匹配,0次或者多次
02 pattern.match()、pattern.search()和re.findall()
match()
函数只检测re
是不是在string
的开始位置匹配, search()
会扫描整个string
查找匹配, 也就是说match()
只有在0位置匹配成功的话才有返回,如果不是开始位置匹配成功的话,match()
就返回none
。
match()
和search()
方法都只是匹配出一个符合条件的字符串,若想要匹配出字符串中所有符合条件的子字符串的话,可以使用re.findall()
方法。findall()
方法将所有符合条件的所有字符串组成列表返回,无符合条件的字符串则返回空列表。
mystr = '今天的天气真好,天气真的好'
pattern = re.compile('天气')
match = pattern.match(mystr)
print(match)
# match结果
# None
# 这是因为这个字符串开头是今天而不是天气,所以结果为None
search = pattern.search(mystr)
print(search)
# search结果
# <_sre.SRE_Match object; span=(3, 5), match='天气'>
# 只有一个结果,返回的是Match object,可以用search[0]得到该字符串
find = re.findall(pattern, mystr)
print(find)
# find结果
# ['天气', '天气']
# 得到两个符合条件的子字符串
03 pattern贪婪和非贪婪
正则表达式通常用于在文本中查找匹配的字符串。Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;非贪婪则相反,总是尝试匹配尽可能少的字符。在"*","?","+","{m,n}"后面加上?,使贪婪变成非贪婪。
比如,针对文本dxxxdxxxd
,表达式(d)(\w+)(d)
中的\w+
将匹配第一个d
和最后一个d
之间的所有字符xxxdxxx
。
待匹配的字符串
dxxxdxxxd
正则表达式一,贪婪模式
(d)(\w+)(d)
正则表达式一,匹配结果
dxxxdxxxd
正则表达式二,非贪婪模式
(d)(\w+?)(d)
正则表达式二,匹配结果
dxxxd