文章目录
一.简介
正则表达式(Regular expression)是一组由字母和符号组成的特殊文本,它可以用来从文本中找出满足你想要的格式的句子。
比如我们在网站中看到对用户名规则做出了如下限制:只能包含小写字母、数字、下划线和连字符,并且限制用户名长度在3~15个字符之间,如何验证一个用户名是否符合规则呢?我们使用以下正则表达式:
以上的正则表达式可以接受john_doe、jo-hn_doe、john12_as,但不能匹配A1,因为它包含了大写字母而且长度不到3个字符。
二.简单的模式:字符匹配
元字符 | 描述 |
---|---|
. | 句号匹配任意单个字符除了换行符 |
[] | 字符种类,匹配方括号内的任意字符,中括号内每个字符是或(or)的关系 |
[^] | 否定的字符种类,匹配除了方括号里的任意字符 |
* | 匹配0次或无限次,重复在*号之前的字符 |
+ | 匹配1次或无限次,重复在+号之前的字符 |
? | 匹配0次或1次,重复在?号之前的字符 |
{n,m} | 匹配num个大括号之前的字符(n<=num<=m) |
(xyz) | 字符集又称做组,匹配与xyz完全相等的字符串,每个字符是且(and)的关系 |
| | 或运算符,匹配符号前或后的字符 |
\ | 转义字符,用于匹配一些保留字符[]、()、{ }… *、+、?、^、$、\、l |
^ | 从字符串开始位置开始匹配 |
$ | 从字符串末端开始匹配 |
反斜杠后面跟普通字符实现特殊功能
特殊字符 | 描述 |
---|---|
\d | 匹配数字,相当于[0-9] |
\D | 不匹配数字,相当于[^0-9] |
\s | 匹配空白字符(包括空格、换行符、制表符等),相当于[\t\n\r\f\v] |
\S | 与\s相反,相当于[^\t\n\r\f\v] |
\w | 匹配中文,下划线,数字,英文,相当于[a-zA-z0-9_] |
\W | 与\w相反,匹配特殊字符,如$、&、空格、\n、\t等 |
\b | 匹配单词的开始或结束 |
\B | 与\b相反 |
1.元字符
(1)提取字符串a中所有的数字
import re
a = '亚索3佐伊2剑圣6女枪4女警'
r = re.findall('[0-9]', a)
print(r)
运行结果:
(2)提取字符串a中所有非数字
import re
a = '亚索3佐伊2剑圣6女枪4女警'
r = re.findall('[^0-9]', a)
print(r)
运行结果:
(3)找到字符串中间字母是d或e的单词
import re
a = 'xyz,xcz,xfz,xdz,xaz,xez'
r = re.findall('x[de]z', a)
print(r)
运行结果:
(4)找到字符串中间字母不是d或e的单词
import re
a = 'xyz,xcz,xfz,xdz,xaz,xez'
r = re.findall('x[^de]z', a)
print(r)
运行结果:
(5)找到字符串中间字母是d或e或f的单词
import re
a = 'xyz,xcz,xfz,xdz,xaz,xez'
r = re.findall('x[d-f]z', a)
print(r)
运行结果:
2.概括字符集
(1)提取字符串a中所有的数字
import re
a = 'Excel 12345\tWord\n23456_PPT$12lr'
r = re.findall('\d',a)
print(r)
运行结果:
(2)提取字符串a中所有非数字
import re
a = 'Excel 12345\tWord\n23456_PPT$12lr'
r = re.findall('\D',a)
print(r)
运行结果:
(3)可以提取中文,英文,数字和下划线,不能提取特殊字符
import re
a = 'Excel 12345\tWord\n23456_PPT$12lr'
r = re.findall('\w',a)
print(r)
运行结果:
(4)提取特殊字符、空格、\n、\t等
import re
a = 'Excel 12345\tWord\n23456_PPT$12lr'
r = re.findall('\W',a)
print(r)
运行结果:
(5)提取空白字符(包括空格、换行符、制表符等)
import re
a = 'Excel 12345\tWord\n23456_PPT$12lr'
r = re.findall('\s', a)
print(r)
运行结果:
(6)提取非空白字符
import re
a = 'Excel 12345\tWord\n23456_PPT$12lr'
r = re.findall('\S', a)
print(r)
运行结果:
3.数量词
(1)提取大小写字母混合的单词
import re
a = 'Excel 12345Word23456PPT12Lr'
r = re.findall('[a-zA-Z]{3,5}', a)
print(r)
运行结果:
贪婪 与 非贪婪 【Python默认使用贪婪模式】
贪婪:’[a-zA-Z]{3,5}’
先找三个连续的字母,最多找到5个连续的字母后停止。在3个以后且5个以内发现了不是字母的也停止。
非贪婪:’[a-zA-Z]{3,5}?’ 或 ‘[a-zA-Z]{3}’
建议使用后者,不要使用?号,否则你会与下面的?号混淆
(2)匹配0次或无限多次 * 号, * 号前面的字符出现0次或无限次
import re
a = 'exce0excell3excel3'
r = re.findall('excel*', a)
print(r)
运行结果:
(3)匹配1次或者无限多次 +号,+号前面的字符至少出现1次
import re
a = 'exce0excell3excel3'
r = re.findall('excel+', a)
print(r)
运行结果:
(4)匹配0次或1次 ?号,?号经常用来去重复
import re
a = 'exce0excell3excel3'
r = re.findall('excel?', a)
print(r)
运行结果:
4.边界匹配^和$
限制电话号码的位置必需是8-11位才能提取
import re
tel = '13855876681'
r = re.findall('^\d{8,11}$', tel)
print(r)
运行结果:
5.组()
(1)将abc打成一个组,{2}指的是重复几次,匹配abcabc
import re
a = 'abcabcabcxyzabcabcxyzabc'
r = re.findall('(abc){2}', a)
print(r)
运行结果:
(2)可以加入多个组
import re
a = 'abcabcabcxyzabcabcxyzabc'
r = re.findall('(abc)(xyz)', a)
print(r)
运行结果:
6.匹配模式参数
(1)findall第三参数 re.I忽略大小写
import re
a = 'abcFBIabcCIAabc'
r = re.findall('fbi', a, re.I)
print(r)
运行结果:
(2)多个模式之间用 | 连接在一起
import re
a = 'abcFBI\nabcCIAabc'
r = re.findall('fbi.{1}', a, re.I | re.S) # 匹配fbi然后匹配任意一个字符包括\n
print(r)
运行结果:
注:.句号,不匹配\n,但是使用re.S之后,匹配所有字符包括换行符
1).re.I(re.IGNORECASE): 忽略大小写
2).re.M(MULTILINE): 多行模式,改变’^’和’$’的行为
3).re.S(DOTALL): 点任意匹配模式,改变’.’的行为
4).re.L(LOCALE): 使预定字符类 \w \W \b \B \s \S 取决于当前区域设定
5).re.U(UNICODE): 使预定字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性
6).re.X(VERBOSE):详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释
7.re.sub替换字符串
(1)把FBI替换成BBQ
import re
a = 'abcFBIabcCIAabc'
r = re.sub('FBI','BBQ',a)
print(r)
运行结果:
(2)把FBI替换成BBQ,第4参数写1,证明只替换第一次,默认是0(无限替换)
import re
a = 'abcFBIabcFBIaFBICIAabc'
r = re.sub('FBI','BBQ',a,1)
print(r)
运行结果:
注意:虽然字符串的内置方法 字符串.replace 也可以进行替换,但是正则表达式更强大
(3)拓展知识
import re
a = 'abcFBIabcFBIaFBICIAabc'
def 函数名(形参):
pass
r = re.sub('FBI',函数名,a,1)
print(r)
分析:如果找到了FBI这个子串,会将FBI当成参数传到形参中,pass是什么都没返回,所以FBI被空字符串代替了。如果想替换,可以加返回值
运行结果:
(4)把函数当参数传到sub的列表里,实现把业务交给函数去处理,例如将FBI替换成$FBI$
import re
a = 'abcFBIabcFBIaFBICIAabc'
def 函数名(形参):
分段获取 = 形参.group() # group()在正则表达式中用于获取分段截获的字符串,获取到FBI
return '$' + 分段获取 + '$'
r = re.sub('FBI',函数名,a)
print(r)
运行结果:
8.把函数做为参数传递
将字符串中大于等于5的替换成9,小于5的替换成0
import re
a = 'C52730A52730D52730'
def 函数名(形参):
分段获取 = 形参.group()
if int(分段获取) >= 5:
return '9'
else:
return '0'
r = re.sub('\d',函数名,a)
print(r)
运行结果:
9.group分组
(1)取组
import re
a = 'life is short,i use python'
r = re.search('life(.*)python',a)
print(r.group(1))
等同于
import re
a = 'life is short,i use python'
r = re.findall('life(.*)python',a)
print(r)
运行结果:
(2)分组
import re
a = "123abc456"
r = re.search("([0-9]*)([a-z]*)([0-9]*)", a)
print(r.group()) # 不在里面写数字,返回整体
print(r.group(0)) # 写0和空是一样的
print(r.group(1))
print(r.group(2))
print(r.group(3))
运行结果:
- 正则表达式中的三组括号把匹配结果分成三组 group() 同group(0)就是匹配正则表达式整体结果 group(1) 列出第一个括号匹配部分,group(2) 列出第二个括号匹配部分,group(3) 列出第三个括号匹配部分。
- 没有匹配成功的,re.search()返回None
- 当然正则表达式中没有括号,group(1)肯定不对了。
(3)拓展知识
import re
a = 'life is short,i use python,i love python'
r = re.search('life(.*)python(.*)python',a)
print(r.group(0)) # 完整正则匹配
print(r.group(1)) # 第1个分组之间的取值
print(r.group(2)) # 第2个分组之间的取值
print(r.group(0,1,2)) # 以元组形式返回3个结果取值
print(r.groups()) # 返回就是group(1)和group(2)
运行结果:
三.正则表达式函数
1.re.compile
re.compile是将正则表达式转换为模式对象,这样可以更有效率匹配。使用compile转换一次之后,以后每次使用模式时就不用进行转换.
pattern:写正则表达式
flags:匹配模式
从compile()函数的定义中,可以看出返回的是一个匹配对象,它单独使用就没有任何意义,需要和findall(), search(), match()搭配使用。
compile()与findall()一起使用,返回一个列表。
(1)compile配合findall
import re
a = '0355-67796666'
b = re.compile(r'\d+-\d{8}')
r = re.findall(b,a)
print(r)
运行结果:
# 直接使用findall
import re
a = '0355-67796666'
r = re.findall(r'\d+-\d{8}',a)
print(r)
运行结果:
由上可知,二种方式是一样的结果,一般我们会直接使用findall
(2)compile配合search
import re
a = '0355-67796666'
正则 = re.compile(r'\d+-\d{8}')
r = re.search(正则,a)
print(r.group())
运行结果:
(3)compile配合match
import re
a = '0355-67796666'
正则 = re.compile(r'\d+-\d{8}')
r = re.match(正则,a)
print(r.group())
运行结果:
2.re.match
match 从字符串的第一个字符开始匹配,如果未匹配到返回None,匹配到则返回一个对象。
match判断正则表达式是否从开始处(首字母)匹配一个字符串,例如第一个不是\d(数字),返回None
import re
a = '83C72D1D8E67'
r = re.match('\d',a)
print(r) # 返回对象所在位置
print(r.group()) # 返回找到的结果,例如8
print(r.span()) # 返回一个元组表示匹配位置(开始,结束)
运行结果:
3.re.search
Search与match有些类似,只是搜索整个字符串然后第一个匹配到指定的字符则返回值,未匹配到则返回None。获取值得方法也需要通过group().
从字符串开始往后匹配,一匹配到则返回一个对象。需要通过group来获取匹配到的值。
# search 遍历字符串,找到正则表达式匹配的第一个位置
import re
a = 'A83C72D1D8E67'
r = re.search('\d',a)
print(r)
print(r.group())
运行结果:
4.re.findall
Findall是匹配出字符串中所有跟指定值有关的值,并且以列表的形式返回。未匹配到则返回一个空的列表。匹配出指定字符的所有值,并以列表返回值。
import re
a = 'A83C72D1D8E67'
r = re.findall('\d',a)
print(r)
运行结果: