day14 正则表达式
什么是正则表达式:一种可以让复杂字符串问题变简单的工具
写逻辑困难时可用
正则表达式由正则符号组成
符号:匹配类、匹配次数、检测类、分支分组
# 案例1、判断输入内容是否为合法电话号码
# 要求:长度是11位、全部是数字字符、第一位是1开头、第二位是3~9
tel = ''
#法1
if len(tel) == 11:
if tel[0] == '1' and tel[1] in '3456789':
flag = True
# pass
for x in tel[2:]:
if not '0' <= x <= '9':
flag = False
break
if flag:
print('合法')
else:
print('不合法')
else:
print('不合法')
#法2:
from re import fullmatch
result = fullmatch(r'1[3-9]\d{9}',tel)
if result:
print('合法')
else:
print('不合法')
#案例2,提取所有数字
message = ' : , : , ...' #文本信息
#['','','',...],数字列表
#法1:
result = []
str1 = ''
for x in message:
if '0' <= x <= '9':
str1 += x
else:
if str1:
result.append(str1)
str1 = ''
if str1:
result.append(str1)
print(result)
#法2:
from re import findall
#findall:正则里查找相关的工具
result = findall(r'\d+',message)
print(result)
1、模块:fullmatch
fullmatch(正则表达式,字符串):判断字符串是否满足正则表达式描述的规则,不符合结果为None
使用正则表达式解决问题时,都是在描述字符串规则
2、所有匹配类符号:约束字符
①普通符号:在正则表达式中表示本身的字符就是普通符号
②特殊意义符号:
符号 | 意义 |
---|---|
. | 匹配任意一个字符 |
\d | 匹配任意一个数字字符 |
\s | 匹配任意一个空白字符(空格、\t、\n) |
\w | 匹配任意一个数字、字母、下划线或者中文 |
\D、\S、\W | 匹配功能和小写字母完全相反(非) |
[字符集] | 匹配在字符集中任意一个字符 |
注:特殊符号在[]中仍有效
[\u4e00-\u9fa5]:匹配任意一个中文或者任意一方大写字母
^ :匹配不在字符集中的任意一个字符,放在[]最前面才有特殊功能
3、匹配次数符号(不能单独使用,要接在匹配类符号后)
符号 | 意义 |
---|---|
* | 任意次(包括0) |
+ | >=1次 |
? | 0或者1次 |
{N} | N次 |
{M,N} | M到N次 |
{M,} | 至少M次 |
{,N} | 至多N次 |
from re import fullmatch
result = fullmatch(r'abc', 'abc') #字符串规则:abc,匹配结果:abc
print(result)
result = fullmatch(r'.bc', '0bc')
print(result)
result = fullmatch(r'...', 'abc')
print(fullmatch(r'a*b', 'b'))
print(fullmatch(r'\d*b','0b'))
print(fullmatch(r'.*b', 'b'))
print(fullmatch(r'[A-Z]*b','kkllb'))
print(fullmatch(r'a+b', 'ab'))
print(fullmatch(r'a?b', 'ab'))
print(fullmatch(r'a{3}b', 'aaab'))
4.贪婪和非贪婪(用的少,了解):
匹配次数不确定的时候匹配模式分为贪婪模式和非贪婪模式。默认是贪婪
贪婪:匹配成功有多种结果的情况下,取最大值(类似经济学中的经济人定义)
非贪婪:在匹配次数符号后接?
fullmatch,需要全部符合
match,开头符合即匹配成功
match(正则表达式,字符串)
from re import match
print(match(r'a\db', 'a3bpppppp'))
print(match(r'a.+b', 'a12bkskshjwbkksowbuik'))
print(match(r'a.+b','ahhjibiioolbiop0[bjkkp'))
print(match(r'a.+?b','ahhjibiioolbiop0[bjkkp'))
#partice: 写正则表达式可以匹配任意一个整数字符串(不考虑0)
print(fullmatch(r'[+-]?[1-9]\d*', '123'))
5、() :分组
在正则表达式中,用()将正则表达式中的部分内容括起来表示一个整体
①整体操作,控制某个部分
②重复:在正则中通过\n来重复前面第n个分组匹配到的结果
③捕获:获取匹配结果某部分,分为手动捕获和自动捕获
自动捕获:获取匹配结果分组匹配到的内容,findall
手动捕获:代码中写出分组匹配到的内容,fullmatch
获取正则对应匹配结果:匹配对象.group()
获取某个分组对应的匹配结果:匹配对象.group(分组数)
6、| : 分支(类似或者)
正则1 | 正则2 :先用正则1匹配,匹配失败则用正则2匹配
from re import fullmatch
print(fullmatch(r'([a-z]{2}\d{3})*', ''))
print(fullmatch(r'([a-z]{2})(\d{3})=\2\1{2}', 'mn891=891mnmn'))
from re import findall
message = ' 年龄:18岁 , 身高:178 , 体重:120, 月薪:3000元 , 房租:1000元'
print(findall(r'\d+', message))
print(findall(r'\d+元', message))
print(findall(r'(\d+)元', message)) #元:筛选作用
print(fullmatch(r'\d{2}[a-z]{3}|\d{2}[\u4e00-\u9fa5]{3}'), '23wer')
print(fullmatch(r'\d{2}([a-z)|[\u4e00-\u9fa5])', '23为人体'))
7、检测类符号(不影响字符串长度):在匹配成功的情况下,检测指定的位置是否符合相应要求
①\b :检测是否是单词边界
单词边界:空白符号,换行符号,标点符号,字符串开头/结尾
underground
under ground
under
ground
under,ground
②^ : 检测是否是字符串开头
③$ : 检测是否是字符串结尾
④search(正则,字符串):获取字符串中第一个满足条件的子串
⑤转义符号:特殊符号前加\,使之普通化
⑥re模块:提供和正则表达式相关的函数
模块 | 作用 |
---|---|
fullmatch | 完全匹配,匹配成功返回匹配对象,失败为None |
martch | 开头匹配,匹配成功返回匹配对象,失败为None |
saerch | 查找,匹配第一个满足正则的子串 |
findall | 捕获,获取所以满足正则的子串,返回值是列表,元素为匹配的字符串 |
finditer | 返回迭代器,内容为正则匹配对象 |
sub(正则,字符串1,字符串2) | 替换,将字符串2中所有满足正则的字串用字符串1替换 |
splite | 切割,满足正则的子串作为切割点 |
from re import fullmatch
print(fullmatch(r'\d{2},\ba', '23,a'))
str1 = '123adfsg666韶关市,jji999 900'
print(findall(r'\d+', str1))
print(findall(r'\b\d+', str1))
from re import search
print(search(r'\d{3}', 'shhko677与死神hh556hb'))
print(search(r'^1[3-9]\d{9}$', '13018222713'))
print(fullmatch(r'[\u4e00-\u9fa5]\.\d+', '好.111'))
print(fullmatch(r'\d\*\d','2*4'))
from re import finditer, split, sub
str1 = 'hi还曾经四次加哦就啊m9088,huhihj vyih788 i90'
print(findall(r'\d+', str1))
result = finditer(r'\d+', str1)
print(result)
print(next(result))
print(list(result))
print(split(r'\d+', str1))
print(sub('d+|[a-z]+', 'A', str1))