正则表达式
1.概念
正则是一种可以让复杂的字符串问题变得简单的工具。并不是python特有的语法,所有的高级语言都支持。
如:判断手机号是否是正确的。
方法一:用常规方法
def is_tell(num: str):
if len(num) != 11:
return False
for x in num:
if not x.isdigit():
return False
if num[0] == 1:
return True
if "3" < +num[1] <= "9":
return True
return False
print(is_tell("1233456"))----false
图二
from re import fullmatch
tel=input("输入一个电话号码")
result = fullmatch(r"1[3-9]\d{9}",tel)
print(result)
不管通过正则表达式解决什么问题,写的时候都用正则表达式描述的规则
2.python的re模块
re模块是python用来支持正则表达式的模块,模块中包含了所有和正则相关的函数
fullmatch(正则表达式 , 字符串)-----判断正则表达式和指定的字符串是否完全匹配
成功返回匹配对象,失败返回None
from re import fullmatch
#引入正则模块
3.正则语法
匹配类符号
1.)普通符号------在正则表达式表示符号本身的符号
result = fullmatch(r"abc","abc")
print(result)
匹配
2).----匹配任何一个字符
result = fullmatch(r"a.c","abc")
print(result)
匹配
result = fullmatch(r"..c","abc")
print(result)
匹配---两个点匹配两个字符
3.) \d----匹配任意一个数字字符
result = fullmatch(r"a\dc","a0c")
print(result)
匹配
4.) \s----匹配任意一个空白字符
空白字符-----能产生空白效果的字符.例如:空格、换行、水平制表符
result = fullmatch(r"a\sc","a c")
print(result)
匹配
5.) \D—匹配任意一个不是数字字符
result = fullmatch(r"a\Dc","a+c")
print(result)
匹配
6.) \S—匹配任意一个非空白字符
result = fullmatch(r"a\Sc","a c")
print(result)
None
7.) [字符集]—匹配字符集中的任意一个字符
result = fullmatch(r"a[1-9]c","a7c")
print(result)
匹配
规律:
[abc] 匹配a或者b或者c
[abc\d] 匹配a或者b或者c或者数字
[1-9] 匹配任意数字
[a-z] 匹配任意一个小写字母
[A-Z] 匹配任意一个大写字母
[a-zA-Z] 匹配任意一个字母
[\u4e00--\u9fa5] 匹配任意一个中文
8.)[ ^字符集]------不在字符集中的任意一个字符
result = fullmatch(r"a[^1-9]c","abc")
print(result)
匹配
4.匹配次数:
1.)* -----(0次或多次数)控制*前面字符的次数
a*-----多个a
result = fullmatch(r"a*c","aaaaaac")
print(result)
result = fullmatch(r"\d*c","1234455c")
print(result)
- ±-----一次或多次
result = fullmatch(r"\d+c","123c")
print(result)
- ?------0次或1次
result = fullmatch(r"\d?c","1c")
print(result)
4.{ }
{M,N}-----M到N次
result = fullmatch(r"[a-z]{1,4}c","aaac")
print(result)
{M,}------至少M次
result = fullmatch(r"[a-z]{1}c","aaac")
print(result)
{,N}----最多N次
result = fullmatch(r"[a-z]{,2}c","aac")
print(result)
{N}----N次
result = fullmatch(r"[a-z]{2}c","aac")
print(result)
5.贪婪与非贪婪
当匹配次数不确定的时候,匹配模式为贪婪与非贪婪两种。默认是贪婪的
贪婪:在匹配成功的时候有多种匹配结果,贪婪取最多次数对应的匹配结果
from re import match
#match (正则表达式,字符串)-----判断字符串开头是否符合正则表达式描述的规则
result = match(r"a.+b","amb计算bxxxbmn")
print(result)
amb、amb计算、amb计算bxxxb
#结果默认取:amb计算bxxxb
非贪婪模式:次数最小的模式(在次数后面+?)
*?、+?、??、{M,N}?、{M,}?、{,N}?
result = match(r"a.+?b","amb计算bxxxbmn")
print(result)
amb #在次数后面加?,非贪婪模式
6.分组-----()
1.整体-----将正则表达式中的一部分作为一个整体进行相关操作
result = fullmatch(r"(\d\d[a-z]{2})+","12ab34av")
print(result)
#整体结构不断重复
2.重复------可以在正则表达式中通过\M来重复它前面的第M个分组匹配结果
23m23、34m34
result = fullmatch(r"(\d\d)[a-z]\1","12a12")
print(result)
#整体内容不断重复
3.捕获–只获取正则表达式中分组匹配到的结果
result = fullmatch(r"(\d\d)([a-z]{3})=\2\1","12aas=aas12")
print(result)
7.分支—|
正则1|正则2|正则3|------匹配可以和多个正则中任意一个正则匹配的字符串–相等于选择
result = fullmatch(r"(\d\d)|([a-z]{3})","aas")
print(result)
#a234b amjhb
result = fullmatch(r"a(\d{3}|[a-z]{3})b","a123b")
print(result)
如果想要正则表达式中的一部分实现多选一的效果,变化的部分用分组表示
8.转义符号
1.在本身具备特殊功能的特殊意义的符号前加" \ ",让这个字符体现本身含义
匹配任意一个小数对应的字符串
result = fullmatch(r"\d+\.\d+","2.3566")
print(result)
如:+23
result = fullmatch(r"\+\d{2}","+23")
print(result)
如:?23
result = fullmatch(r"\?\d{2}","?23")
print(result)
2.[]里的转义符号
单独存在有特殊意义的符号(+、*、?.),在[]中特殊意义会自动消失
result = fullmatch(r"[?]\d{2}","?23")
print(result)
本身在中括号中有特殊功能的符号,如果要表示普通符号必须加" \ "
result = fullmatch(r"a[MN-]b","a-b")
print(result)
result = fullmatch(r"a[M\-N]b","a-b")
print(result)
3.检测类符号(了解)
在匹配成功的情况下,检测检测类符号所在的位置是否符号相关要求
1.\b----检测是否是单词边界
单词边界:可以将两个单词分开的符号都是单词边界,比如:空白符号、英文标点符号、字符串开头和字符串结尾
result = fullmatch(r'abc\b mn', 'abc mn')
print(result)
#首先去掉\b,与后面字符匹配,在判断是否有单词边界
2.\B-----检测是否不是单词边界
message = '203mn45,89 司机34kn;23;99mll==910,230 90='
result = findall(r'\B\d+\B', message)
print(result)
#['03', '4', '34', '9', '1', '3']一个又一个判断
3.^----检测是否是字符串开头
message = '203mn45,89 司机34kn;23;99mll==910,230 90='
result = findall(r'^\d+', message)
print(result)
#['203']
4.$—检测是否是字符串结尾
message = '203mn45,89 司机34kn;23;99mll==910,230 90='
result = findall(r'\d+$', message)
print(result)
#[]
9.模块常见函数
1.fullmatch(正则表达式,字符串)-----完全匹配,判断整个字符串是否符合描述规则—不考虑贪婪
result = fullmatch(r"a[M\-N]b","a-b")
print(result)
2.match(正则表达式,字符串)-----匹配字符串开头,判断字符串开头是否符合正则表达式的规则。匹配成功返回匹配对象,
result = match(r'\d{3}', '823介绍数据库')
print(result)
3.search(正则表达式,字符串)----获取字符串中第一个能够和正则匹配成功的子串。
result = search(r'\d{3}', 'ba203还是678说')
print(result)
203
4.findall(正则表达式,字符串)----获取符合条件的字符串,返回一个列表
result = finditer(r'\d{3}', 'ba203还是678说kk0222jksn就是23311')
print(list(result))
#['203', '678', '022', '233']
5.finditer(正则表达式,字符串)-----提取符合条件的字符串,返回一个迭代器,迭代器中的元素是每个子串对应的匹配结果
result = finditer(r'\d{3}', 'ba203还是678说kk0222jksn就是23311')
print(list(result))
#[<re.Match object; span=(2, 5), match='203'>, <re.Match object; span=(7, 10), match='678'>,
6.split(正则表达式,字符串-)-----将字符串中所有满足正则的子串作为切割点对字符进行切割
from re import split
str1 = '123aMKnb嗑生嗑死aKKssa923b==='
# 将str1中的a和k和b作为切割点对字符串进行切割
result = split(r'a|k|b', str1)
print(result)
#['123', 'MKn', '嗑生嗑死', 'KKss', '923', '===']
7.sub(正则表达式,字符串1,字符串2)-----相当于replace,将字符串2中所有满足正则的子串都替换成字符串1
from re import sub
result = sub(r'\d+', '+', 'ba203还是678说kk0222jksn就是23311')
print(result)
#ba+还是+说kk+jksn就是+
2.匹配对象
1)获取匹配结果:匹配对象.group( )
from re import search
result = search(r'\d+', 'ba678203还是说kk0222jksn就是23311')
print(result.group())
#678203
2)某个分组的匹配结果:匹配对象.group(分组数)
from re import search
result = search(r'(\d+)([a-z]+)', 'ba67820ghjkk0222jksngfgh23311ghjh')
print(result.group(1))
#67820
3)获取匹配结果在原字符串中的位置:匹配对象.span( )
from re import search
result = search(r'(\d+)([a-z]+)', 'ba67820ghjkk0222jksngfgh23311ghjh')
print(result.span(1))
(2,7)---下标
3.参数
1)忽略大小写(?i)
from re import fullmatch
result = fullmatch(r'(?i)abc', 'aBC')
print(result)
匹配
作业
利用正则表达式完成下面的操作:
一、不定项选择题
-
能够完全匹配字符串"(010)-62661617"和字符串"01062661617"的正则表达式包括(ABD )
A.
r"\(?\d{3}\)?-?\d{8}"
B.r"[0-9()-]+"
C.r"[0-9(-)]*\d*"
D.r"[(]?\d*[)-]*\d*"
-
能够完全匹配字符串"back"和"back-end"的正则表达式包括(A BC D )
A.r'\w{4}-\w{3}|\w{4}'
B.r'\w{4}|\w{4}-\w{3}'
C.r'\S+-\S+|\S+'
D.r'\w*\b-\b\w*|\w*'
-
能够完全匹配字符串"go go"和"kitty kitty",但不能完全匹配“go kitty”的正则表达式包括(A D)
A.r'\b(\w+)\b\s+\1\b'
B.r'\w{2,5}\s*\1'
C.r'(\S+) \s+\1'
D.r'(\S{2,5})\s{1,}\1'
-
能够在字符串中匹配"aab",而不能匹配"aaab"和"aaaab"的正则表达式包括(B )
A.r"a*?b"
B.r"a{,2}b"
C.r"aa??b"
D.r"aaa??b"
二、编程题
1.用户名匹配
要求: 1.用户名只能包含数字 字母 下划线
2.不能以数字开头
3.⻓度在 6 到 16 位范围内
from re import fullmatch
result=fullmatch(r"[a-zA-Z _][0-9 a-z A-Z _]{6,16}", )
- 密码匹配
要求: 1.不能包含!@#¥%^&*这些特殊符号
2.必须以字母开头
3.⻓度在 6 到 12 位范围内
from re import fullmatch
result=fullmatch(r"[a-zA-Z][a-zA-Z 0-9]{5,11}", )
- ipv4 格式的 ip 地址匹配
提示: IP地址的范围是 0.0.0.0 - 255.255.255.255
from re import search
result=search(r"\d[,3]\.\d[,3]\.\d[,3]\.\d[,3] ", )
- 提取用户输入数据中的数值 (数值包括正负数 还包括整数和小数在内) 并求和
例如:“-3.14good87nice19bye” =====> -3.14 + 87 + 19 = 102.86
from re import findall
result=findall(r"-?\d+\.?\d+", "-3.14good87nice19bye")
print(result)
sum1=0
for x in result:
b=float(x)
sum1+=b
print(sum1)
#102.86
- 验证输入内容只能是汉字
from re import fullmatch
result=fullmatch(r"[\u4e00-\u9fa5]+", "密码密码")
print(result)
- 匹配整数或者小数(包括正数和负数)
from re import fullmatch
result=fullmatch(r"-?\d+\.?\d+", "-123.123")
print(result)
-
验证输入用户名和QQ号是否有效并给出对应的提示信息
要求:
用户名必须由字母、数字或下划线构成且长度在6~20个字符之间
QQ号是5~12的数字且首位不能为0from re import fullmatch username=input("请输入账号") if fullmatch(r"[0-9 a-zA-Z _]{6,20}", username): print(f"{username}有效") else: print(f"{username}无效") pw=input("请输入账号") if fullmatch(r"[1-9]\d{4,11}", pw): print(f"{pw}有效") else: print(f"{pw}无效")
6.拆分长字符串:将一首诗的中的每一句话分别取出来
poem = ‘窗前明月光,疑是地上霜。举头望明月,低头思故乡。’
from re import split result = split(r';', '窗前明月光,疑是地上霜。举头望明月,低头思故乡。') print(result)
from re import findall
result = findall(r'[\u4e00-\u9fa5]{5}', '窗前明月光,疑是地上霜。举头望明月,低头思故乡。')
for x in range(len(result)):
print(result[x])