python学习笔记DAY14(常用模块_re)
这是我个人的学习笔记,都赖于(egon老师)的分享,以下是老师博客的原地址:
https://www.cnblogs.com/xiaoyuanqujing/articles/11640888.html
python常用模块
十三、re模块
正则就是用一堆特殊符号表达一种规律。(re模块是用来做正则匹配的)
## 我们之前学习过的匹配方法
"hello".replace("l","x",1) # 用新的值替换指定的某个值
"hello".find("ee") # 查找某个值所在的索引位置
## 正则匹配
import re
# \w\W
re.findall("\w","Hello nida 512 妮妲")
# 结果:['h', 'e', 'l', 'l', 'o', 'n', 'i', 'd', 'a', '5', '1', '2']
# 结果说明:匹配字母数字及下划线
re.findall("\W","Hello nida 512 妮妲")
# 结果:[' ', ' ', ' ']
# 结果说明:匹配字母非数字及下划线
# \s\S
re.findall("\s","Hello nida 512 妮妲 \t\n\r\f")
# 结果:[' ', ' ', ' ', ' ', '\t', '\n', '\r', '\x0c']
# 结果说明: 匹配任意空白字符(相当于匹配到 \t\n\r\f)
re.findall("\S","Hello nida 512 妮妲")
# 结果:['H', 'e', 'l', 'l', 'o', 'n', 'i', 'd', 'a', '5', '1', '2', '妮', '妲']
# 结果说明:匹配任意非空白字符
#\n与\t
re.findall("\n","Hello nida 512 \n妮妲")
# 结果:['\n']
# 结果说明:匹配\n
re.findall("\t","Hello nida 512 \t妮妲")
# 结果:['\t']
# 结果说明:匹配\t
#\d与\D
re.findall("\d","Hello nida 512 \n妮妲")
# 结果:['5', '1', '2']
# 结果说明:匹配任意数字(0-9)
re.findall("\D","Hello nida 512 \t妮妲")
# 结果:['H', 'e', 'l', 'l', 'o', ' ', 'n', 'i', 'd', 'a', ' ', ' ', '\t', '妮', '妲']
# 结果说明:匹配任意非数字
#\A与\Z
re.findall("\Ahe","hello nida 512 妮妲")
# 结果:['he']
# 结果说明:匹配字符串开始位置
re.findall("512\Z","Hello nida 512")
# 结果:['123']
# 结果说明:匹配字符串结束,如果存在换行,只匹配到换行前
#^与$
re.findall("^he","hello nida 512 妮妲")
# 结果:['he']
# 结果说明:匹配字符串开始位置
re.findall("512$","Hello nida \n512")
# 结果:['123']
# 结果说明:匹配字符串结束
# ====重复匹配====
# .
re.findall("a.b","a8b") # 结果:['a8b'] 说明:.匹配所有字符(除了\n)
re.findall("a.b","a8b a#b a b aaab") # 结果:['a8b', 'a#b', 'a b', 'aab']
re.findall("a.b","a\nb") # 结果:[] 说明:除了换行,匹配所有字符
re.findall("a.b","a\nb",re.S) # 结果:['a\nb'] 说明:加了S之后,换行符也可以匹配
re.findall("a.b","a\nb",re.DOTALL) # 结果:['a\nb'] 说明:同上
# *(*号前面的字符允许有 0-无数个)
re.findall("ab*","bbbbbb") # 结果:[] 说明:没有“a”所以无法匹配
re.findall("ab*","a") # 结果:['a'] 说明:"b"为0个,也可以匹配
re.findall("ab*","abbbbbb") # 结果:['abbbbbb'] 说明:一个"a"可以拿到后面所有"b"
# ?(?匹配前面的字符 0-1 个)
re.findall("ab?","bbbbbb") # 结果:[] 说明:没有“a”所以无法匹配
re.findall("ab?","a") # 结果:['a'] 说明:"b"为0个,也可以匹配
re.findall("ab?","abbbbbb") # 结果:['ab'] 说明:一个"a"可以拿到后面一个"b"
# + (+匹配前面的字符 1-无数个)
re.findall("ab+","a") # 结果:[] 说明:没有一个+号前面的字符,无法匹配
re.findall("ab+","abbb") # 结果:["abbb"] 说明:一个"a"可以拿到后面所有"b"
# 匹配所有包含小数在内的数字(整数1-无数个,小数点0到1个,小数0-无数个)
re.findall("\d+\.?\d*","asdfasdf123as1.13dfa12adsf1asdf3")
#====配合使用====
# .* (默认为贪婪匹配)
re.findall("a.*b","a1b22222222b") # 结果:['a1b22222222b'] 说明:只要首尾符合标准,中间所有值都拿到
# .*?(非贪婪匹配 推荐使用)
re.findall('a.*?b','a1b22222222b') # 结果:['a1b'] 说明:首尾符合标准,中间允许有一个值
#{n,m}
re.findall("ab{3}","abbbbb") # 结果:['abbb'] 说明:符合条件,匹配到n个字符
re.findall("ab{2,3}","abbbbb")# 结果:['abbb'] 说明:符合条件,匹配n-m次字符
re.findall("ab{1,}","abbbbb")# 结果:['abbbbb'] 说明:符合条件,匹配1-无数次(相当于+)
re.findall("ab{0,}","abbbbb")# 结果:['abbbbb'] 说明:符合条件,匹配0-无数次(相当于*)
# [] 用来匹配一组字符
re.findall("a[1*-]b","a1b a*b a-b") # 结果:['a1b', 'a*b', 'a-b'] 说明:[]内都为普通字符
re.findall("a[^1*-]b","a1b a*b a-b a=b") # 结果:['a=b'] 说明:[]内 ^ 表示取反
re.findall("a[0-9]b","a1b a*b a-b ") # 结果:['a1b'] 说明:在[]中 - 在中间,表示某一个范围
re.findall("a[a-z]b","a1b a*b a-b aeb") # 结果:['aeb'] 说明:中间字符必须是范围内的值
re.findall('a[a-zA-Z]b','a1b a*b a-b a=b aeb aEb') # 结果:['aeb', 'aEb'] 说明:中间字符必须是范围内的值
# \
# re.findall('a\\c','a\c') # 结果:报错
# 在python解释器中执行\\双斜杠时会发生转意,所以会抛出异常
re.findall(r'a\\c','a\c') # 结果:['a\\c']
# r表示告诉解释器使用rawstring,就是原生字符串,把正则内所有字符当成普通字符处理
re.findall('a\\\\c','a\c') # 结果:['a\\c'] 说明:同上
#():分组
re.findall('ab+','ababab123') # 结果:['ab', 'ab', 'ab']
re.findall('(ab)+123','ababab123') # 结果:['ab'] 说明:匹配到末尾的ab123中的ab
re.findall('(?:ab)+123','ababab123') #结果:['ababab123'] 说明:匹配到末尾123前面的所有ab和()号外的字符
re.findall('href="(.*?)"','<a href="http://www.baidu.com">点击</a>') # 结果:['http://www.baidu.com']
# 说明:匹配""内的字符
re.findall('href="(?:.*?)"','<a href="http://www.baidu.com">点击</a>') # 结果 ['href="http://www.baidu.com"']
# 说明:匹配""内的字符和括号外的字符
#|
re.findall('compan(?:y|ies)','Too many companies have gone bankrupt, and the next one is my company')
# 结果:['companies', 'company'] 说明:匹配括号外字符与括号内 以|区分 的所有 字符 的匹配 结果字符
# ==== re 模块提供的方法 ====
re.findall("a","abdca") # 返回在"abdca"中查找到的"a"
re.search('e','alex make love').group() # 结果: e 如果找不到返回None
#e,只到找到第一个匹配,然后返回一个包含匹配信息的对象,该对象可以通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。
re.match('e','alex make love')# 结果:None 说明:同上search,不过是在字符串开始处匹配,可以用search+^ 来代替
re.split('[ab]','abcd') # 结果:['', '', 'cd'] 说明:先按"a"分割得到" "和"bcd",再按b分割得到" "和"cd"
re.sub("a","A","nida nian",1) # 结果:nidA nian 说明:旧值替换为新值,如果没有指定替换替换几次的n,默认全部替换
re.subn("a","A","nida nian") # 结果:('nidA niAn', 2) 说明:结果包含了替换的次数统计
obj=re.compile('\d{2}')
obj.search('abc123eeee').group() #12
obj.findall('abc123eeee')#['12'],重用了obj
- 补充一
import re
print(re.findall("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>")) #['h1']
print(re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>").group()) #<h1>hello</h1>
print(re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>").groupdict()) #<h1>hello</h1>
print(re.search(r"<(\w+)>\w+</(\w+)>","<h1>hello</h1>").group())
print(re.search(r"<(\w+)>\w+</\1>","<h1>hello</h1>").group())
- 补充二
import re
#使用|,先匹配的先生效,|左边是匹配小数,而findall最终结果是查看分组,所有即使匹配成功小数也不会存入结果
#而不是小数时,就去匹配(-?\d+),匹配到的自然就是,非小数的数,在此处即整数
#
print(re.findall(r"-?\d+\.\d*|(-?\d+)","1-2*(60+(-40.35/5)-(-4*3))")) #找出所有整数['1', '-2', '60', '', '5', '-4', '3']
#找到所有数字:
print(re.findall('\D?(\-?\d+\.?\d*)',"1-2*(60+(-40.35/5)-(-4*3))")) # ['1','2','60','-40.35','5','-4','3']
#计算器作业参考:http://www.cnblogs.com/wupeiqi/articles/4949995.html
expression='1-2*((60+2*(-3-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))'
content=re.search('\(([\-\+\*\/]*\d+\.?\d*)+\)',expression).group() #(-3-40.0/5)
#为何同样的表达式search与findall却有不同结果:
print(re.search('\(([\+\-\*\/]*\d+\.?\d*)+\)',"1-12*(60+(-40.35/5)-(-4*3))").group()) #(-40.35/5)
print(re.findall('\(([\+\-\*\/]*\d+\.?\d*)+\)',"1-12*(60+(-40.35/5)-(-4*3))")) #['/5', '*3']
#看这个例子:(\d)+相当于(\d)(\d)(\d)(\d)...,是一系列分组
print(re.search('(\d)+','123').group()) #group的作用是将所有组拼接到一起显示出来
print(re.findall('(\d)+','123')) #findall结果是组内的结果,且是最后一个组的结果
- 补充三
# ========= 补充
#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
#在线调试工具:tool.oschina.net/regex/#
import re
s='''
http://www.baidu.com
egon@oldboyedu.com
你好
010-3141
'''
#最常规匹配
# content='Hello 123 456 World_This is a Regex Demo'
# res=re.match('Hello\s\d\d\d\s\d{3}\s\w{10}.*Demo',content)
# print(res)
# print(res.group())
# print(res.span())
#泛匹配
# content='Hello 123 456 World_This is a Regex Demo'
# res=re.match('^Hello.*Demo',content)
# print(res.group())
#匹配目标,获得指定数据
# content='Hello 123 456 World_This is a Regex Demo'
# res=re.match('^Hello\s(\d+)\s(\d+)\s.*Demo',content)
# print(res.group()) #取所有匹配的内容
# print(res.group(1)) #取匹配的第一个括号内的内容
# print(res.group(2)) #去陪陪的第二个括号内的内容
#贪婪匹配:.*代表匹配尽可能多的字符
# import re
# content='Hello 123 456 World_This is a Regex Demo'
#
# res=re.match('^He.*(\d+).*Demo$',content)
# print(res.group(1)) #只打印6,因为.*会尽可能多的匹配,然后后面跟至少一个数字
#非贪婪匹配:?匹配尽可能少的字符
# import re
# content='Hello 123 456 World_This is a Regex Demo'
#
# res=re.match('^He.*?(\d+).*Demo$',content)
# print(res.group(1)) #只打印6,因为.*会尽可能多的匹配,然后后面跟至少一个数字
#匹配模式:.不能匹配换行符
content='''Hello 123456 World_This
is a Regex Demo
'''
# res=re.match('He.*?(\d+).*?Demo$',content)
# print(res) #输出None
# res=re.match('He.*?(\d+).*?Demo$',content,re.S) #re.S让.可以匹配换行符
# print(res)
# print(res.group(1))
#转义:\
# content='price is $5.00'
# res=re.match('price is $5.00',content)
# print(res)
#
# res=re.match('price is \$5\.00',content)
# print(res)
- 总结
- 尽量使用泛匹配模式 .*
- 尽量使用非贪婪模式:.*?
- 使用括号得到匹配目标:用group(n)去取得结果
- 有换行符就用re.S:修改模式
#re.search:会扫描整个字符串,不会从头开始,找到第一个匹配的结果就会返回
# import re
# content='Extra strings Hello 123 456 World_This is a Regex Demo Extra strings'
#
# res=re.match('Hello.*?(\d+).*?Demo',content)
# print(res) #输出结果为None
#
# import re
# content='Extra strings Hello 123 456 World_This is a Regex Demo Extra strings'
#
# res=re.search('Hello.*?(\d+).*?Demo',content) #
# print(res.group(1)) #输出结果为
#re.search:只要一个结果,匹配演练,
import re
content='''
<tbody>
<tr id="4766303201494371851675" class="even "><td><div class="hd"><span class="num">1</span><div class="rk "><span class="u-icn u-icn-75"></span></div></div></td><td class="rank"><div class="f-cb"><div class="tt"><a href="/song?id=476630320"><img class="rpic" src="http://p1.music.126.net/Wl7T1LBRhZFg0O26nnR2iQ==/19217264230385030.jpg?param=50y50&quality=100"></a><span data-res-id="476630320" "
# res=re.search('<a\shref=.*?<b\stitle="(.*?)".*?b>',content)
# print(res.group(1))
#re.findall:找到符合条件的所有结果
# res=re.findall('<a\shref=.*?<b\stitle="(.*?)".*?b>',content)
# for i in res:
# print(i)
#re.sub:字符串替换
import re
content='Extra strings Hello 123 456 World_This is a Regex Demo Extra strings'
# content=re.sub('\d+','',content)
# print(content)
#用\1取得第一个括号的内容
#用法:将123与456换位置
# import re
# content='Extra strings Hello 123 456 World_This is a Regex Demo Extra strings'
#
# # content=re.sub('(Extra.*?)(\d+)(\s)(\d+)(.*?strings)',r'\1\4\3\2\5',content)
# content=re.sub('(\d+)(\s)(\d+)',r'\3\2\1',content)
# print(content)
# import re
# content='Extra strings Hello 123 456 World_This is a Regex Demo Extra strings'
#
# res=re.search('Extra.*?(\d+).*strings',content)
# print(res.group(1))
# import requests,re
# respone=requests.get('https://book.douban.com/').text
# print(respone)
# print('======'*1000)
# print('======'*1000)
# print('======'*1000)
# print('======'*1000)
# res=re.findall('<li.*?cover.*?href="(.*?)".*?title="(.*?)">.*?more-meta.*?author">(.*?)</span.*?year">(.*?)</span.*?publisher">(.*?)</span.*?</li>',respone,re.S)
# # res=re.findall('<li.*?cover.*?href="(.*?)".*?more-meta.*?author">(.*?)</span.*?year">(.*?)</span.*?publisher">(.*?)</span>.*?</li>',respone,re.S)
#
#
# for i in res:
# print('%s %s %s %s' %(i[0].strip(),i[1].strip(),i[2].strip(),i[3].strip()))'''
- 作业练习
import re
# 1、匹配密码,密码必须是由6位数字与字母组成,并且不能是纯数字也不能是纯字母
# 1.1 知识点:# ?!pattern,表示在没有配到pattern的字符串的前提下,再进行后续的正则表达式匹配,后续匹配仍然从被匹配字符串的头开始
# 1.2 答案:
print(re.search("(?!^[0-9]+$)(?!^[a-zA-Z]+$)^[0-9A-Za-z]{6}$","123asf").group()) # 123asf
# 1.3 解释:
# 上述正则的意思为:在匹配(?!^[0-9]+$)以及(?!^[a-zA-Z]+$)过后,如果字符串成功后在从头去匹配(?!^[a-zA-Z]+$),最终匹配完。
# 2、匹配密码,密码强度:强,必须包含大写,小写和数字,和特殊字符(!,@,#,%,&),且大于6位
# 2.1 知识点:# ?=pattern,表示在配到pattern的字符串的前提下,再进行后续的正则表达式匹配,后续匹配仍然从被匹配字符串的头开始
# 2.2 答案:
# while True:
# pwd = input("please your password: ").strip() # 比如输入:Aa3@adf123
# pwd_pattern= re.compile("(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[!@#%&])^([a-zA-Z0-9!@#%&]){6,}$")
# if pwd_pattern.search(pwd) is None:
# print("密码强度不够")
# else:
# break
# 2.3 解释:
# 上述正则表达式的意思:
#(1)首先是(?=.*[A-Z])匹配,.*表示密码中可以包含多个字符,[A-Z]代表密码中需要包含至少一个大写字母,注意一定不要去掉.*写成(?=[A-Z]),那样表示密码只能由一个字符组成,该字符是大写字母
#(2)其次是(?=.*[a-z])匹配,同上,确保密码中必须至少有一个小写字母
#(3)然后是(?=.*[0-9])匹配,同上,确保密码中必须至少有一个数字
#(4)然后是(?=.*[!@#%&])匹配,同上,,确保密码中必须至少有一个特殊符号!@#%&
#(5)最后是^([a-zA-Z0-9!@#%&]){6,}$,确保密码是由[a-zA-Z0-9!@#%&]字符构成,至少有6位
# 3、匹配email
# print(re.findall("(?:[a-zA-Z0-9]+)@(?:[0-9a-zA-Z]+).com","18611323113@163.com xxx@qq.com"))
# 4、匹配身份证
# your_id=input(">>: ").strip()
# print(re.findall("^([0-9]){17}([0-9]|X)$",your_id)) # 17个数字组成,最后一个字符可以是数字或X
# 5、匹配用户名,包含字母或者数字,且8位
# print(re.findall("^[0-9a-zA-Z]{8}$","egonlinh"))
# 5.1、要求输入的内容只能是汉字
# name=input('>>: ').strip()
# print(re.search(r'[\u4E00-\u9fa5]+',name))
# 6、取出字符串里的数字
# print(re.findall(r'\d+(?:\.\d+)?', 'sww123kw11.333e2lkd'))
# 7、取出所有负整数
# print(re.findall(r'-\d+', '-12,3,54,-13.11,64,-9')) # 错误答案
# print(re.findall(r'(?!-\d+\.\d+)-\d+', '-12,3,54,-13.11,64,-9')) # 正确答案
# 8、所有数字
# print(re.findall(r'\-?\d+(?:\.\d+)?', '-12.9,3.92,54.11,64,89,-9,-45.2'))
# 9、所有负数
# print(re.findall(r'\-\d+(?:\.\d+)?', '-12.9,3.92,54.11,64,89,-9,-45.2'))
# 10、所有的非负浮点数
print(re.findall(r'\d+\.\d+', '-12.9,3.92,54.11,64,89,-9,-45.2'))
# 11、
msg = """
中文名 贝拉克·侯赛因·奥巴马
外文名 Barack Hussein Obama II
别名 欧巴马
性 别 男
国籍 美国
民 族 德裔族
出生地 美国夏威夷州檀香山
出生日期 1961年8月4日
职 业政治家、律师、总统
毕业院校 哥伦比亚大学,哈佛大学
信 仰新教
主要成就 1996年伊利诺伊州参议员
主要成就 美国第56届、57届总统 2009年诺贝尔和平奖获得者 时代周刊年度风云人物2008、2011 任期内清除本·拉登
代表作品 《我相信变革》《我父亲的梦想》《无畏的希望》
所属政党美国民主党
血 型 AB型
学 院西方学院
妻 子 米歇尔·拉沃恩·奥巴马
"""
#外文名
print(re.findall("外文名 (.*)",msg))
#出生日期
print(re.findall('出生日期 (\d{4})年(\d+)月(\d+)日',msg))
#妻子姓名
print(re.findall('妻 子 (\S+)',msg))

浙公网安备 33010602011771号