day - 16 正则表达式

本文详细介绍了正则表达式的各种应用场景,包括检测类符号、匹配次数、分组和分支等核心概念。通过丰富的实例,帮助读者掌握正则表达式的使用技巧。

正则表达式

1. 检测类符号
from re import fullmatch, findall
  1. \b - 检测是否是单词边界
"""
单词边界:凡是可以将两个单词分开的符号都是单词边界,比如:空白字符,标点符号,字符串开头和结尾

注意:检测类符号是在匹配成功得情况下看检测类型在的位置是否符合要求
"""
re_str = r'abc \b123'
print(fullmatch(re_str, 'abc 123'))

re_str = r'\b\d\b'
result = findall(re_str, ' 99 nj一71,0 卭,8.回8复23')
print(result)   #['0', '8']
# findall (同时满足两个数字的)
  1. \B - 检测是否不是单词边界
re_str = r'\B\d\d\B'
result = findall(re_str, '99nj一33卭回复2')
pritn(result)  # ['33']
  1. ^ - 检测是否是字符串开头
re_str = r'^\d\d'  # ^放在开头
result = findall(re_str, '65nj一卭回复23')
print(result) # ['65']
  1. $ - 检测是否是字符串结尾
re_str = r'\d\d$
result = findall(re_str, '99nj一卭回复233')
print(result)  # 33

re_str = r'^\d\d\d$'  # 必须同时满足  只有三个数字
result = findall(re_str, '123')
print(result)  #['123']
2. 匹配次数
from re import fullmatch, match
三个a: 'aaa' == 'a{3}'
三个数字: '\d\d\d' == 'a{3}'
25个大写字母: '[A-Z]{2,5}'
  1. (*) - 0次或者多次 (任意次数)
"""
a*  -   a出现0次或多次
\d*  -   \d出现0次或多次,每次的一个\d可以是任意一个数字
[abc]*  -  [abc] 出现0次或多次,每次的[abc]都可以在a、b、c中任意一个
"""
re_str = r'a\d*b'   # 任意数字
print(fullmatch(re_str, 'ab'))
print(fullmatch(re_str, 'a5461b'))
  1. (+)- 1次或多次 (至少一次)
re_str = r'a\d+b'   # ab中至少有1个数字
print(fullmatch(re_str, 'ab'))    # None
print(fullmatch(re_str, 'a5461b'))
  1. ? - 0次或一次
re_str = r'[-+]?[1-9]\d'  # +或者- 有一次或者没有出现
print(fullmatch(re_str, '+16'))
print(fullmatch(re_str, '-16'))
print(fullmatch(re_str, '16'))
  1. { }
"""
{N}      -   匹配N次
1[3-9]\d{9}
{M,N}      -   匹配M到N次,M和N都可以取到
{M,}     -   匹配至少M次
{,N}    -    匹配最多N次
"""
re_str = r'1a{2,5}2'  # a的次数2到5次
print(fullmatch(re_str, '1aaaa2'))

re_str = r'1a{3}2'  # a出现的次数必须是3次
print(fullmatch(re_str, '1aaa2'))
  1. 贪婪和非贪婪
"""
在匹配次数不确定的时候才有贪婪和非贪婪两种模式
贪婪:在能匹配成功的前提下取匹配次数最多次数 (默认)
非贪婪:在能匹配成功的前提下匹配次数最少的次数 (在匹配次数后面加?)
"""
re_str = r'a.+?b'     # match末尾不一定要是b,字符串中有b就行
print(fullmatch(re_str, 'a组队副本b看四大b'))
print(match(re_str 'azxbvbkjsb知道你发你'))

re_str = r'a.+b'
print(fullmatch(re_str, 'a扫is建档立卡那种类型等级哦ib'))
print(match(re_str, 'asjzixb123basdb拉三等奖'))      # 5次  9次  13次

re_str = r'a.+?b'
print(fullmatch(re_str, 'a扫is建档立卡那种类型等级哦ib'))
print(match(re_str, 'asjdxb123basdb拉三等奖'))      # 4次  8次  12次
3.分组和分支
from re import fillmatch
  1. 分组 - ()
"""
用法1: 将正则表达式中的一部分作为一个整体,进行一个整体相关操作,比如控制次数
用法2: 重复 -  使用\M来重复前面第M个分组中的内容
用法3: 捕获
"""
re_str = r'([a-z]{3}\d{2}){3}'  # 整体控制次数
print(fullmatch(re_str, 'amn23asd43adc12'))

# 22a24a25a45
re_str = r'(\d{2}a){3}\d{2}'
print(fullmatch(re_str, '22a24a25a45'))

# '23abc23'  /  '93ace93'
re_str = r'(\d\d)abc\1'  #重复括号1
# print(fullmatch(re_str, '12abc21'))  # None

re_str = r'(\d\d{2})([\u4e00-\u9fa5])\2\1'
print(fullmatch(re_str, '小梅9=13=13=小梅9'))

  1. 分支 - |
"""
正则表达式1 | 正则表达式2   -  先让正则1和字符进行匹配,如果成功就成功,如果失败和正则2匹配
                            如果正则2成功救过匹配成功,否则匹配失败(两个正则只有一个成功结果就成功)
"""
# '23abc' / 'MKMabc
re_str = r'\d{2}abc|[A-Z]{3}abc'
print(fullmatch(re_str, '23abc'))

re_str = r'(\d{2}|[A-Z]{3})abc'
print(fullmatch(re_str, '93abc'))
print(fullmatch(re_str, 'XFFabc'))

  1. 转义符号
# 在本身具备特殊功能或者特殊意义的符号前加\,让其功能或者意义消失,表示一个普通符号

# '32.21' / '93.93'
re_str = r'[1-9]\d\.\d{2}'
print(fullmatch(re_str, '93.93'))

# '2+3
re_str = r'\d\+\d'
print(fullmatch(re_str, '4+8'))

# 注意:独立具备特殊功能的符号在[]中功能会自动消失,例如:+、*、?、.、(、)、
# 本身在[]中有特殊意义的就要特别注意: ^、-、[]
re_str = r'\d[+]\d'
re模块
import re
import re import * #导入re的所有变量
  1. compile(正则表达式) - 创建一个正则表达式对象
re_obj = re.compile(r'\d{3})
print(re_obj)   # re.compile('\\d{3}')

result =re_boj.fullmatch('123')
print(result)   # <re.Match object; span=(0, 3), match='123'>

fullmatch(r'\d{3}', 123)
print(result)   # <re.Match object; span=(0, 3), match='123'>
  1. 匹配类的方法
"""
1.fullmatch
fullmatch(正则表达式,字符串)
正则表达式对象.fullmatch
判断整个字符串是否符合正则表达式描述的规则,如果不符合返回None,符合返回匹配对象

2.match
match(正则表达式,字符串)
正则表达式对象.match(字符串)  -  判断字符开头是否符合正则表达上描述的规则,如果不符合返回None,符合返回匹配对象
"""
result = match(r'\d{3}-[a-z]{2,5}', '993-asd就是设计是')
print(result)   # <re.Match object; span=(0, 7), match='993-asd'>

1. 获取匹配结果
# 匹配对象.group()  /  匹配对象.group(0) -  获取整个正则表达式匹配结果
# 匹配对象.group(N)  -  获取正则表达式中第N个分组匹配到的结果
print(result.group())   # 993-asd

result = match(r'(\d{3}-)([a-z]{2,5})', '993-asd就是设计是')
print(result.group(1))  # 993-
print(result.group(2))  # asd

2.获取匹配结果在原字符中的位置
# 匹配对象.span()  #  993-asd (0, 7)  在原序列中的位置
# 匹配对象.span(N) #  asd (4, 7)

3.获取原字符串
# 匹配对象.string
print(result.string)  # 993-asd就是设计是
  1. 查找类方法
"""
search(正则表达式,字符串)
正则表达式对象.search(字符串)  -  获取字符串中第一个满足正则表达式的字串,如果没有放回None,否则返回匹配对象
"""
result = search(r'\d{3}', 'shasd1354车厢内993asdz-zlxka913')
print(result)  # <re.Match object; span=(5, 8), match='135'>


"""
findall(正则表达式,字符串)
正则表达式对象.findall(字符串)  -   获取正则字符串中所有满足正则表达式的字串,以列表的方式返回,列表中的元素是字符串
"""

str1 = 'asd13avv93奥斯丁-呢欧安45,。a933'
result = findall(r'\d+', str1)
print(result)  # ['13', '93', '45', '933']

result = findall(r'[\u4e00-\u9fa5]\d+', str1)
print(result)  # ['安45']

# 如果正则中有分组,findall只提取匹配结果中分组匹配到的内容
result = findall(r'[\u4e00-\u9fa5](\d+)', str1)
print(result)  # ['45']

result = findall(r'\d+-[a-z]+', 'anva1321-sd都难得adm=dma;l')
print(result)  # ['1321-sd']

result = findall(r'\d+(-[a-z]+)', 'anva1321-sd都难得adm=dma;l')
print(result)  ['-sd']

result = findall(r'(\d+)-([a-z]+)', 'anva1321-sd都难得adm=dma;l')
print(result, type(result))  # [('1321', 'sd')]  外面是列表 里面是元组

"""
finditer(正则表达式,字符串)
正则表达式对象.finditer(字符串)  -  获取字符串中所有满足正则表达式的字串,返回值是迭代器,迭代器的元素是匹配对象
"""

str1 = 'asd13avv93奥斯丁-呢欧安45,。a933'
result = finditer(r'\d+, str')
print(list(result))

group 提取
str1 = 'asd13avv93奥斯丁-呢欧安45,。a933'
result = finditer(r'\d+', str1)
print('结果:', [x.group() for x in result])    # 结果: ['13', '93', '45', '933']

result = finditer(r'(\d+)-([a-z]+)', 'hshs899-mn生死狙击2-mkl==-892-ma=计算机')
print('分组1的匹配结果:', [x.group(1) for x in result])
  1. 切割
"""
split(正则表达式,字符串, 最大切割数)
正则表达式对象.split(字符串)   -   将字符串中所有满足正则表达式的字串作为切割点对字符串进行切割
"""
str1 = '按时欧安32懊恼93apofa阿金怄气2341oasnv=23怄气'
sesult = split(r'\d+', str1)   # 从数字开始切
print(result)   # ['按时欧安', '懊恼', 'apofa阿金怄气', 'oasnv=', '怄气']

str2 = '安山东,奥迪方清平。安排搜房全皮肤,怄气佛。哦if水电费'
result = split(r'[,。]', str2)
print(result)  # ['安山东', '奥迪方清平', '安排搜房全皮肤', '怄气佛', '哦if水电费']

result = split(r'[,。]', str2, 3)  # 这里3表示只切3次
print(result)  # ['安山东', '奥迪方清平', '安排搜房全皮肤', '怄气佛。哦if水电费']
  1. 替换
"""
sub(正则表达式,字符串,字符串2)
正则表达式对象.sub(字符串1,字符串2)  -  将字符串2中所有满足正则表达式的字串都替换成字符串1
"""
result = sub(r'\d+', '+', '奥数等你13jasdfj=qe1')  # \d+1个或多个数字
print(result)   # 奥数等你+jasdfj=qe+

result = sub(r'\d', '+', '奥数等你13jasdfj=qe1')  # \d每个都替换
print(result)   # 奥数等你++jasdfj=qe+

result = sub(r'\d', '+', '奥数等你13jasl47dfj=qe1', 3)  # 3表示只替换前三个
print(result)   # 奥数等你++jasl+7dfj=qe1   
匹配参数
from re import fullmatch, S, I

匹配参数 1. 1.单行匹配、2.忽略大小写

  1. 单行匹配和多行匹配
"""
默认是多行匹配。
多行匹配的时候. 不能和\n(换行)匹配;单行匹配的时候.可以和\n匹配
"""
# 多行匹配
print(fullmacth(r'a.b, 'a\nb)# None
      
# 单行匹配
# S是从re模块中导入
print(fullmatch(r'a.b', 'a\nb', flags=S))   # <re.Match object; span=(0, 3), match='a\nb'>
print(fullmatch(r'(?s)a.b', 'a\nb'))  # <re.Match object; span=(0, 3), match='a\nb'>
#                 (?s) 可以不导入S
  1. 忽略大小写
"""
默认不忽略大小写
忽略大小写的时候,大写字母可以对应的小写字母匹配,小写字母也可以和对应的大写字母匹配
"""
print(fullmatch(r'[a-z]{3}123', 'aSc123'))  # None

# 忽略大小写
print(fullmatch(r'[a-z]{3}123', 'aSC123', flags=I))   # <re.Match object; span=(0, 6), match='aSc123'>
print(fullmatch(r'(?i)[a-z]{3}123', 'adZ123'))  # <re.Match object; span=(0, 6), match='adZ123'>

# 单行匹配和忽略大小写同时进行
print(fullmatch(r'abc.123', 'ABC\n123', flags=I|S))  # <re.Match object; span=(0, 7), match='ABC\n123'>
print(fullmatch(r'(?si)abc.123', 'ABC\n123', ))

作业

一、不定项选择题
  1. 能够完全匹配字符串"(010)-62661617"和字符串"01062661617"的正则表达式包括( D)

A.r"\(?\d{3}\)?-?\d{8}"
B. r"[0-9()-]+"
C.r"[0-9(-)]*\d*"
D.r"[(]?\d*[)-]*\d*"

  1. 能够完全匹配字符串“back”和“back-end”的正则表达式包括(B,C, 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*”

  2. 能够完全匹配字符串“go go”和“kitty kitty”,但不能完全匹配“go kitty”的正则表达式包括(A,B,C)
    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”

  3. 能够在字符串中匹配“aab”,而不能匹配“aaab”和“aaaab”的正则表达式包括(B,D)
    A. r“a*?b”
    B. r“a{,2}b”
    C. r“aa??b”
    D. r“aaa??b”

二、编程题

1.用户名匹配

​ 要求: 1.用户名只能包含数字 字母 下划线

​ 2.不能以数字开头

​ 3.⻓度在 6 到 16 位范围内

result = r'^\D\w{5,15}'
print(fullmatch(result, 'k564981'))
  1. 密码匹配

​ 要求: 1.不能包含!@#¥%^&*这些特殊符号

​ 2.必须以字母开头

​ 3.⻓度在 6 到 12 位范围内

re_str = r'[a-zA-Z]\w{5,11}'
print(fullmatch(re_str, 'aasda12sd'))
  1. ipv4 格式的 ip 地址匹配
    提示: IP地址的范围是 0.0.0.0 - 255.255.255.255
  1. 提取用户输入数据中的数值 (数值包括正负数 还包括整数和小数在内) 并求和
list1 = '-3.14good87nice19bye'
re_str = compile(r'\-\d\.?\d+|\d+')
num1 = re_str.finditer(list1)
  1. 验证输入内容只能是汉字
re_str = r'[\u4e00-\u9fa5]'
print(findall(re_str, '12a阿萨a德啊'))
  1. 匹配整数或者小数(包括正数和负数)
re_str = r'(\-|\+)?\d+(\.\d+)?)'
  1. 验证输入用户名和QQ号是否有效并给出对应的提示信息

    要求:
    用户名必须由字母、数字或下划线构成且长度在6~20个字符之间
    QQ号是5~12的数字且首位不能为0

  2. 拆分长字符串:将一首诗的中的每一句话分别取出来

    ​ poem = '窗前明月光,疑是地上霜。举头望明月,低头思故乡。

poem = '窗前明月光,疑是地上霜。举头望明月,低头思故乡。'
nexus = split(r'[,。]', poem)
print(nexus)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值