正则表达式
表达式
作为一种让一些复杂字符串问题变得简单的工具。
正则表达式并不属于Python,正则表达式对于所有高级语言都支持。
re模块
re模块作为Python用来支持正则表达式的模块,模块内包含所有相关函数。
匹配类符号
正则语法
– | – |
---|---|
普通符号 | 正则表达式中表示符号本身的符号 |
. | 匹配任意一个字符 |
\d | 匹配任意一个数字字符 |
\s | 匹配任意一个空白字符 |
\D | 匹配任意一个非数字字符 |
\S | 匹配任意一个非空白字符 |
[字符集] | 匹配字符集中的任意一个字符 |
^ | 反义 |
result = fullmatch(r'a\dc', 'a9c') # 匹配a和c中间只能是数字的字符串
print(result)
result = fullmatch(r'a\sc', 'a\tc')
print(result)
result = fullmatch(r'a\Dc', 'a6c')
print(result) # None
result = fullmatch(r'a\Sc', 'a5c')
print(result)
– | – |
---|---|
[abc] | 匹配a或者b或者c |
[abc\d] | 匹配a或者b或者c或者任意一个数字 |
[1-9] | 匹配1到9中任意一个数字 |
[a-z] | 匹配任意一个小写字母 |
[a-zA-Z] | 匹配任意一个字母 |
[\u4e00-\u9fa5] | 匹配任意一个中文 |
字符集
[]中的减号放在两个字符间表示谁到谁,若不在字符之间,就是一个普通字符。
[^字符集] - 匹配不在字符集的字符
result = fullmatch(r'james[^\u4e00-\u9fa5]', 'james2')
print(result)
匹配次数
匹配符号
前四个符号在谁后面控制就是谁的次数。
– | – |
---|---|
* | 0次或任意次数 |
+ | 一次或者多次(至少一次) |
? | 0次或1次 |
{} | {M,N}:M到N次; {M,} :至少M次 ;{,N}:最多N次;{N}:N次 |
# 练习:写一个正则,判断输入的内容是否是一个合法的QQ号(长度是5~12位的数字,第一位不能是0)
qq_num = input('请输入qq:')
result = fullmatch(r'[1-9]\d{4,11}', qq_num)
if result:
print(f'{qq_num}合法')
else:
print(f'{qq_num}不合法')
# 练习:判断输入的内容是否是一个合法的标识符(由字母、数字下划线组成,数字不能开头)
legal_identifier = input('请输入一个合法标识符:')
result = fullmatch(r'[^\d][\da-zA-Z_]*', legal_identifier)
if result:
print(f'{legal_identifier}合法标识符')
else:
print(f'{legal_identifier}不合法标识符')
贪婪和非贪婪
match(正则表达式, 字符串)
判断字符串开头是否符合正则表达式描述的规则。
当匹配次数不确定的时候(*、+、?、{M,N}、{,N}、{M,}),匹配模式分为贪婪和非贪婪,默认是贪婪的。
贪婪
在匹配成功时有多种匹配结果,贪婪取最多次数对应的匹配结果。
(匹配次数不确定的地方,有多种匹配方式都能成功,贪婪取最多次数)
# *、+、?、{M,N}、{,N}、{M,}
result = match(r'a.+b', 'a4465464842b')
print(result) # <re.Match object; span=(0, 12), match='a4465464842b'>
非贪婪
在匹配成功时有多种匹配结果,贪婪取最少次数对应的匹配结果。
(匹配次数不确定的地方,有多种匹配方式都能成功,贪婪取最少次数)
# *?、+?、??、{M,N}?、{,N}?、{M,}?
result = match(r'a.+?b', 'amb计算bxxbmn')
print(result) # <re.Match object; span=(0, 3), match='amb'>
分组和分支
分组
()
– | – |
---|---|
整体 | 将正则表达式中的一部分作为整体进行相关操作 |
重复 | 可以在正则表达式中通过\M来重复他前面的第M个分组的匹配结果 |
捕获 | 只获取正则表达式中的一部分匹配到的结果(分为手动和自动捕获) |
# 23mkj=mkj23
result = fullmatch(r'(\d{2})([a-z]{3})=\2\1', '23mkj=mkj23')
print(result)
# \M只能重复在他出现之前的分组内容,无法重复他后面出现的内容
# result = fullmatch(r'(\d{2})\1\2=([a-z]{2})', '2323mk=mk') # 报错re.error
# print(result)
分支
|
正则1|正则2|正则3|… - 匹配可以和多个正则中任意一个正则匹配的字符串。
# 匹配一个字符串是三个数字或者两个小写字母
# a23b、amkb
result = fullmatch(r'\d{3}|[a-z]{2}', 'ac')
print(result)
# 注意:若想正则表达式中的一部分实现多选一的效果,变化的部分用分组表示
result = fullmatch(r'a(\d{3}|[a-z]{3})b', 'a535b')
print(result)
!
若想正则表达式中的一部分实现多选一的效果,变化的部分用分组表示。
转义符号
转义符号
正则中的转义符号就是在本身具备特殊功能或者特殊意义的符号前加上’',让该符号变成普通符号。
# 显示(肖申克的救赎)
str4 = fullmatch(r'\([\u4e00-\u9fa5]+\)', '(肖申克的救赎)')
print(str4)
[]里面的转义符号
# 单独存在有特殊意义的符号(+、*、?、.),在[]中特殊意义会自动消失
str4 = fullmatch(r'[(\u4e00-\u9fa5)]+', '(肖申克的救赎)')
print(str4)
本身在中括号中有特殊功能的符号,如果要表示普通符号必须加’'。
检测类符号(了解)
– | – |
---|---|
\b | 检测是否是单词边界 |
\B | 检测是否不是单词边界 |
^ | 检测是否是字符串开头 |
$ | 检测是否是字符串结尾 |
单词边界
可以将不同单词区分开的符号都是单词边界,比如:空表符号、英文标点符号、字符串开头、字符串结尾等。
str1 = fullmatch(r'what\b is\b up', 'what is up')
print(str1)
re模块常用函数
常用函数
fullmatch(正则表达式, 字符串) |
---|
完全匹配,判断整个字符串是否符合正则表达式描述的规则,匹配成功返回匹配对象,失败返回空。
result = fullmatch(r'\d{3}', '234')
print(result) # <re.Match object; span=(0, 3), match='234'>
match(正则表达式, 字符串) |
---|
匹配字符串开头,判断字符串开头是否符合正则表达式描述的规则,匹配成功返回匹配对象,匹配失败返回空。
result = match(r'\d{3}', '823介绍数据库')
print(result) # <re.Match object; span=(0, 3), match='823'>
search(正则表达式, 字符串) |
---|
获取字符串中第一个能够和正则匹配的子串,能找到返回匹配对象,找不到返回空。
result = search(r'\d{3}', 'ba203还是678说')
print(result) # <re.Match object; span=(2, 5), match='203'>
findall(正则表达式, 字符串) |
---|
获取字符串中所有满足正则的子串,返回一个列表,列表中的元素是字符串。
注意
如果正则表达式中有分组,会针对分组做自动捕获(只获取分组匹配到的结果)。
result = findall(r'\d{3}', 'ba203还是678说kk0222jksn就是23311')
print(result) # ['203', '678', '022', '233']
finditer(正则表达式, 字符串) |
---|
获取字符串中所有满足正则的子串,返回一个迭代器,迭代器中的元素是每个子串对应的匹配对象。
split(正则表达式, 字符串) |
---|
将字符串中所有满足正则的子串作为切割点对字符串进行切割。
str1 = '123aMKnb嗑生嗑死aKKssa923b==='
# 将str1中的a和b作为切割点对字符串进行切割
result = split(r'a|b', str1)
print(result) # ['123', 'MKn', '嗑生嗑死', 'KKss', '923', '===']
sub(正则表达式, 字符串1, 字符串2) |
---|
将字符串2中所有满足正则的子串都替换成字符串1。
result = sub(r'\d+', '+', 'ba203还是678说kk0222jksn就是23311')
print(result) # ba+还是+说kk+jksn就是+
匹配对象
result = search(r'(\d{3})([A-Z]{2})', '-=2设计师234KM222哈哈宿舍239KH')
print(result) # <re.Match object; span=(6, 11), match='234KM'>
匹配对象.group()
直接获取整个正则表达式对应的匹配结果。
print(result.group()) # '234KM'
匹配对象.group(分组数)
手动捕获某个分组对应的匹配结果。
print(result.group(1)) # '234'
print(result.group(2)) # 'KM'
匹配对象.span()
获取匹配结果在原字符串中的位置。
print(result.span()) # (6, 11)
print(result.span(2)) # (9, 11)
参数
(?i)
匹配忽略大小写。
result = fullmatch(r'(?i)abc', 'AbC')
print(result) # <re.Match object; span=(0, 3), match='AbC'>
(?s)
单行匹配(了解!)。
多行匹配(默认)
匹配的时候.不能和换行(\n)进行匹配。
单行匹配
匹配的时候.可以和换行(\n)进行匹配。
result = fullmatch(r'abc.123', 'abc\n123')
print(result) # None
result = fullmatch(r'(?s)abc.123', 'abc\n123')
print(result) # <re.Match object; span=(0, 7), match='abc\n123'>
'AbC')
print(result) # <re.Match object; span=(0, 3), match='AbC'>
(?s)
单行匹配(了解!)。
多行匹配(默认)
匹配的时候.不能和换行(\n)进行匹配。
单行匹配
匹配的时候.可以和换行(\n)进行匹配。
result = fullmatch(r'abc.123', 'abc\n123')
print(result) # None
result = fullmatch(r'(?s)abc.123', 'abc\n123')
print(result) # <re.Match object; span=(0, 7), match='abc\n123'>