正则表达式
为什么要用正则表达式:用来匹配一类具有相同规则的字符串
规则:
单字符:
. :出换行以外的所有字符
[]:[aoe] [a-w] 匹配集合中任意一个字符
\d:数字 [0-9]
\D:非数字
\w:数字、字母、下划线、中文
\W:非\w
\s:所有的空白字符
\S:非空白字符
数量修饰(控制次数):
* :任意多次 >=0
+:至少一次 >=1
?:可有可无 0次或者1次
{m}:固定m次
{m,}:至少m次
{m,n}:m~n次
边界:
\b :
\B :
$:以XX结尾
^:以XX开头
分组:
():视为一个整体
(ab){4}: 匹配4次ab \2 \1
():子模式\组模式
<>:
子模式举例:
题目:写一个正则,匹配字符串string
import re string = '<p><div><span>猪八戒</span></div></p>' pattern = re.compile(r'<(\w+)><(\w+)>\w+</\2></\1>') # 生成正则 ret = pattern.search(string) # 搜索要匹配的字符串 print(ret)
说明:匹配过程中,需要将div 和 span 分别作为一个整体,所以要用(),而且后面的div以及span要与前面的一致,所以用\2来匹配第二个()中的span,\1来匹配第一个()中的div
运行结果:
ret----- <re.Match object; span=(3, 30), match='<div><span>猪八戒</span></div>'>
贪婪模式: .* 和 .+
.*? :取消贪婪模式
.+?:取消贪婪模式
举例:
string_2 = '<div>一二三四五</div></div></div>' pattern_2 = re.compile(r'<div>.*</div>') # .* 贪婪模式,匹配一二三四五</div></div> pattern_3 = re.compile(r'<div>.*?</div>') # .*? 取消贪婪模式,只匹配到 一二三四五 就结束匹配 ret_2 = pattern_2.search(string_2) ret_3 = pattern_3.search(string_2) print("ret_2 ----", ret_2) # 可以匹配全部的 print("ret_3 ----", ret_3) # 匹配部分
运行结果:
ret_2 ---- <re.Match object; span=(0, 28), match='<div>一二三四五</div></div></div>'> ret_3 ---- <re.Match object; span=(0, 16), match='<div>一二三四五</div>'>
re.I:忽略大小写
re.M:多行匹配
re.S:单行匹配
举例:
1.匹配 string_3 中所有的love
string_3 = '''This is python ! love you very much love her! love everybody!''' pattern = re.compile(r'^love',re.M) # 匹配多行 ret_4 = pattern.findall(string_3) print("ret_4---",ret_4)
运行结果:
ret_4--- ['love', 'love', 'love']
2.匹配 string_4中所有的文字
string_4 = '''<div>沁园春-雪 北国风光, 千里冰封, 万里雪飘。 望长城内外, 惟余莽莽; 大河上下, 顿失滔滔。 山舞银蛇, 原驰蜡象, 欲与天公试比高。 </div>''' pattern_2 = re.compile(r'<div>(.*?)</div>', re.S) ret_5 = pattern_2.findall(string_4) print("ret_5----", ret_5)
运行结果:
ret_5---- ['沁园春-雪\n北国风光,\n千里冰封,\n万里雪飘。 \n望长城内外,\n惟余莽莽;\n大河上下,\n顿失滔滔。 \n山舞银蛇,\n原驰蜡象,\n欲与天公试比高。 \n']
说明:1) . 本身不可以匹配换行符,但是设置成单行模式 re.S后, .就可以匹配换行符了。
2)* 匹配多字符
3)加不加问号则取决于匹配需求,若</div>后面还有另外的</div>,则 ? 可以结束匹配,不会匹配到</div>
相关函数:
match():只找最开始的位置,找不到则作罢
search():从任意位置找
findall():找所有的位置
re.sub(正则表达式1,替换内容2,字符串3) :在字符串3中找到正则1中的内容,然后替换成中间的内容2
替换举例:将love换成hate
string_5 = 'I love you, you love me, ok!' pattern = re.compile(r'love') ret_6 = pattern.sub('hate', string_5) # 或者 ret_6 = re.sub(r'love', 'hate', string_5) print(ret_6)
运行结果:
I hate you, you hate me, ok!
举例替换2: 将string中的数字减去10
import re def fn(a): ret2 = int(a.group()) return str(ret2 - 10) string = "我喜欢的身高是175,175" pattern = re.compile(r'\d+') ret = pattern.sub(fn, string) print(ret)
fn调用时不带括号的说明:1. sub这个函数本身可以将函数作为参数的功能,
2. 然后在调用fn的时候,会将pattern匹配到的字符串自动作为参数传给a,类似于装饰器ddt
运行结果:
我喜欢的身高是165,165