Skip to main content

re

re 模块 (正则表达式)

正则表达式作为多编程语言中的数据匹配工具,实用又简单,预计学习时长 8 小时。这里送上学习笔记和思维导图。

经典示例

import re

# findall
target = 'life is short, i learn python.'
result = re.findall('python', target)
result1 = re.findall('java', target)
# findall是re库的一个重要方法,第一个参数是匹配规则,第二个参数是要匹配的目标字符串,还有第三个参数,我们之后讲,findall返回的结果是一个列表。
# result这行代码的意思是从target中匹配'python',如果匹配到就返回,没有匹配到就返回空列表。
print(result)# 得到的结果是['python']
print(result1)# 得到的结果是[]


# 元字符
target = 'abc acc aec agc adc aic'
result = re.findall('a[de]c', target)
# 这一行中的[de]表示这个位置上的字符是d或者是e都可以匹配出来
print(result)# 得到的结果是['aec', 'adc']

result = re.findall('a[b‐z]c', target)
# 这一行中的[b‐z]表示这个位置上的字符在b‐z范围内都可以匹配出来
print(result)# 得到的结果是['abc', 'acc', 'aec', 'agc', 'adc', 'aic']

result = re.findall('a[^c‐z]c', target)
# 这一行中的[^c‐z]表示这个位置上的字符不在c‐z范围内都可以匹配出来,注意是不在
print(result)# 得到的结果是['abc']


# 示例
text = '我住在3号楼666,我的电话号码是17606000003你后面有事给我打电话,打不通就打17327567890。实在不行就打固定电话010-7788'
result = re.findall('\d{3}[\d-]\d*',text)
# \d{3}代表至少3个数字起匹配(区号和电话号码都满足)
# [\d-]代表后面跟着的可以是数字(电话号码),也可以是-
# \d*代表后面的数字我都要
print(result)#结果是['17606000003', '17327567890', '010-7788']


# 分组
line = "Cats are smarter than dogs"
matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I)
#re.M表示多行匹配,影响 ^ 和 $
#re.I 使匹配对大小写不敏感
if matchObj:
print ("matchObj.group() : ", matchObj.group())#返回所有组
print ("matchObj.group(1) : ", matchObj.group(1)) # 返回组1【注意不是从0开始】
print ("matchObj.group(2) : ", matchObj.groups())# 返回所有组的元组形式
else:
print ("No match!!")


# 替换与检索sub
phone = "2004-959-559 # 这是一个国外电话号码"
# 删除字符串中的 Python注释
num = re.sub(r'#.*$', "", phone)
print ("电话号码是: ", num)
# 删除非数字(-)的字符串
num = re.sub(r'\D', "", phone)
print ("电话号码是 : ", num)

# 将匹配的数字乘以 2
def double(matched):
value = int(matched.group('value'))
return str(value * 2)
s = 'A23G4HFD567'
print(re.sub('(?P<value>\d+)', double, s))


#贪婪与非贪婪
content = '发布于2018/12/23'
result = re.findall('.*?(\d.*\d)', content)
"""
这里的?表示的就是非贪婪模式,第一个.*会尽可能少地去匹配内容
因为后面跟的是\d,所以碰见第一个数字就终止了。
"""
print(result) # ['2018/12/23']

result = re.findall('.*(\d.*\d)', content)
"""
这里的第一个.*后面没有添加问号,表示的就是贪婪模式,第一个.*会尽可能多地去匹配内容
后面跟的是\d,碰见第一个数字并不一定会终止,当它匹配到2018的2的时候,发现剩#下的内容依然满足(\d.*\d),所以会一直匹配下去
直到匹配到12后面的/的时候,发现剩下的23依然满足(\d.*\d),但是如果再匹配下去,匹配到23的2的话,剩下的3就不满足(\d.*\d)了
所以第一个.*就会停止匹配,(\d.*\d)最终匹配到的结果就只剩下23了。
"""
print(result) # ['23']

result = re.findall('.*?(\d.*?\d)', content)
"""
这里的第一个.*?表示非贪婪模式(非贪婪模式就是尽可能少地去匹配字符),匹配到2018前面的'于'之后就停止了
括号里的.*?也是表示非贪婪模式,括号里的内容从2018的2开始匹配,因为后面一个数字是0,那么也就满足了(\d.*?\d)
所以就直接返回结果了,同样的,接下来的18也是这样,一直匹配到23才结束
"""
print(result) # ['20', '18', '12', '23']