正则表达式又称规则表达式(Regular Expression 简写regex)是一种用于字符串匹配模式,通过定义一串特殊规则去匹配符合的字符。常被用来检索、替换那些符合某个模式(规则)的文本。简单来说,正则表达式就是使用:字符串定义规则,并通过规则去验证字符串是否匹配。
正则表达式本身也就是字符串,只是里面的字符都有特别的含义,分为:普通字符串,直接匹配它们,特殊字符(元字符),它们出现在正则表达式字符串中,不是表示直接匹配它们,而是表达一些特别的含义。
可大致分为四个步骤:
需要用到的方法 功能
compile(string,flags=0) 返回一个pattern对象
string:匹配规则字符串内容。 flags:指匹配模式,可以使用按位或运算符“|”让模式同时生效,比如re.I|re.M。flags可以放在compile用来编译正则表达式字符串,也可以放在匹配查询方法中,比如放在.search()中。可以省略。此处不详细讲解。注意:用生成的对象来调用相关方法相比于直接用re来调用,会对正则表达提前缓存,可以重复使用该正则模式对象。pattern可以理解为一个匹配模式。作为新手可以先直接记住一种就可以。
match(pattern,string,flags=0) 从被匹配字符串开头进行匹配,匹配成功返回匹配对象 (包含匹配的信息),匹配不成功返回空None。只匹配开头。
pattern:匹配规则字符串内容。string:被匹配的原始字符串。 flags:跟compile方法一样,可以省略,此处不详细讲解。注意:当用具体pattern对象调用而不是用re调用的话就应该是pattern对象.match(string)。
search(pattern,string,flags=0) 搜索整个字符串,找出匹配的,从前向后,找到第一个 后,就停止,不会继续向后。匹配成功返回匹配对象(包含匹配的信息)。 匹配不成功返回空None。
findall(pattern,string,flags=0) 找出全部匹配项,返回一个列表对象,找不到返回空列表。
下面以匹配普通字符串为列:
import re
s="hello world hellopython hello"
#2、创建一个pattern对象,并设置好匹配规则
p=re.compile(r"hello")
#3、调用方法match,search,findall
result1=p.match(s)
print(result1,type(result1))
result2=p.search(s)
print(result2,type(result2))
result3=p.findall(s)
print(result3,type(result3))
#4、打印匹配对象group()
#以及在原字符串中索引span()
a=result2.group() #返回值类型str
#返回值类型tuple,包括两个元素,
#起始,结束前一位
b=result2.span()
print(a,type(a))
print(b,type(b))
输出结果:
['hello', 'hello', 'hello']
hello
(0, 5)
使用特殊字符(元字符来匹配),可以将其分为5类。示例:
(1)单字符匹配8个
字符 |
功能 |
注意事项 |
. |
匹配除换行符(\n)以外,任意一个字符。 |
\.匹配点本身 |
[] |
匹配[]中列举的字符,可以是很多单个,也可以范围 |
范围写法例如[2-6],[“a”-”b”] |
\d |
匹配数字,即0-9 |
|
\D |
匹配非数字 |
|
\s |
匹配空白,即空格、tab键 |
|
\S |
匹配非空白 |
|
\w |
匹配单词字符,即a-z,A-Z,0-9,_ |
|
\W |
匹配非单词字符 |
import re
#1、单字符匹配(. \d)获取字符串中所有颜色内容
s="""1小草是绿色的
2天空是蓝色的
3云朵是白色的
4油菜花是金黄色的
"""
p=re.compile(r".色")
result=p.findall(s)
print(result)
p=re.compile(r"\d")
result=p.findall(s)
print(result)
#[]的使用
s="""小王,18903114466
小李,16345678912
小明,15977345867
小花,08439872828
"""
#只要是中括号里内容都满足
p=re.compile(r"1[58]")
result=p.findall(s)
print(result)
#也可以写范围比如1-8,表示都有效
p=re.compile(r"..,1[1-8]")
result=p.findall(s)
print(result)
输出结果:
['绿色', '蓝色', '白色', '黄色']
['1', '2', '3', '4']
['18', '15']
['小王,18', '小李,16', '小明,15']
(2)数量匹配6个,放在子表达式后,表示匹配前面的子表达式次数
字符 |
功能 |
|
* |
匹配前一个规则的字符出现0至无数次 |
|
+ |
匹配前一个规则的字符出现1至无数次 |
|
? |
匹配前一个规则的字符出现0次或1次 |
|
{n} |
匹配前一个规则的字符出现n次 |
|
{n,} |
匹配前一个规则的字符出现最少n次 |
|
{m,n} |
匹配前一个规则的字符出现m到n次 |
import re
#2、数量匹配* + {m,n}
#获取字符串每行逗号后面的字符串内容包括逗号本身。
s="""1小草,是绿色的
2天空,是蓝色的
3云朵,是白色的
4油菜花,是金黄色的
"""
p=re.compile(r",.*")
result=p.findall(s)
print(result)
s="""1小草是绿色色色的
1小草是绿色色的
1小草是绿色的
1小草是绿的
"""
p=re.compile(r"绿色*")
result=p.findall(s)
print(result)
s="水稻绿的,树叶绿绿的,小草绿绿绿的"
p=re.compile(r".{2}绿{2,3}")
result=p.findall(s)
print(result)
输出结果:
[',是绿色的', ',是蓝色的', ',是白色的', ',是金黄色的']
['绿色色色', '绿色色', '绿色', '绿']
['树叶绿绿', '小草绿绿绿']
(3)边界匹配4个
字符 |
功能 |
|
^ |
匹配字符串的开始 |
放在子表达式前 |
$ |
匹配字符串的结束 |
放在子表达式后 |
\b |
匹配单词的开始或结束 |
|
\B |
匹配不是单词开头或结束的位置 |
import re
#3、边界匹配
s="""001-茄子价格-30
002-白菜价格-20
003-苦瓜价格-80
"""
#提取所有水果编号,
p=re.compile(r"^\d+",re.M)
result=p.findall(s)
print(result)
#提取所有水果价格,
p=re.compile(r"\d+$",re.M)
result=p.findall(s)
print(result)
输出结果:
['001', '002', '003']
['30', '20', '80']
4、分组匹配(2)
字符 |
功能 |
|
| |
匹配左右任意一个表达式 |
|
() |
将匹配的内容里一部分抠出来就用括号 |
抠出的内容不止一个就放到元组里 |
import re
#4、分组匹配
s="""1小草,小草是绿色的
2天空,天空是蓝色的
3云朵,云朵是白色的
4油菜花,油菜花是金黄色的
"""
#选择每行逗号前面的字符串,不包括逗号
p=re.compile(r"^(.*),",re.M)
result=p.findall(s)
print(result)
#选择每行逗号前面的字符串,包括逗号并分组存储
p=re.compile(r"^(.*)(,)",re.M)
result=p.findall(s)
print(result)
输出结果:
['1小草', '2天空', '3云朵', '4油菜花']
[('1小草', ','), ('2天空', ','), ('3云朵', ','), ('4油菜花', ',')]
(5)贪婪与懒惰:?
贪婪:当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。以这个表达式为例:a.*b,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,它会匹配整个字符串aabab。这被称为贪婪匹配。
懒惰:也就是匹配尽可能少的字符。前面给出的限定符都可以被转化为懒惰匹配模式,只要在它后面加上一个问号?。这样.*?就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复。现在看看懒惰版的例子吧:a.*?b匹配最短的,以a开始,以b结束的字符串。如果把它应用于aabab的话,它会匹配aab(第一到第三个字符)和ab(第四到第五个字符)。往往我们更需要惰性匹配。
用法\语法 |
功能 |
*? |
重复任意次,但尽可能少重复 |
+? |
重复1次或更多次,但尽可能少重复 |
?? |
重复0次或一次,但尽可能少重复 |
{n,m}? |
重复n到m次,但尽可能少重复 |
{n,}? |
重复n次以上,但尽可能少重复 |
import re
#5、贪婪与惰性
s="Title "
#将<>内的内容都提取出来,贪婪情况
p=re.compile(r"<.*>")
result=p.findall(s)
print(result)
#将<>内的内容都提取出来,惰性情况
p=re.compile(r"<.*?>")
result=p.findall(s)
print(result)
输出结果:
['Title ']
['', '', '', ' ']