正则表达式

正则表达式

---------------------认识正则表达式

---------------------匹配类符号

---------------------匹配次数相关符号

---------------------分组和分支

---------------------检测类符号

一、认识正则表达式

# 1.什么是正则表达式 -  一种可以让复杂的字符串问题变得简单的工具

# 案例1:判断输入的内容是否是一个合法的电话号码
# 要求:a.长度11位 b.全部都是数字字符 c.第一位是1  d.第二位:3~9

tel = '17282282922'

# 方法1:不使用正则
if len(tel) == 11:
    if tel[0] == '1' and tel[1] in '3456789':
        flag = True
        for x in tel[2:]:
            if not '0' <= x <= '9':
                flag = False
                break
        if flag:
            print('合法')
        else:
            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 = '年龄: 18岁, 身高: 170, 体重: 120斤, 月薪: 3000元, 房租: 1000元'

# 方法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
result = findall(r'\d+', message)
print(result)

二、匹配类符号

from re import fullmatch

# 1.fullmatch函数
'''
fullmatch(正则表达式, 字符串)  -  判断字符串是否满足正则表达式描述的规则,如果不满足,结果就是None

不管使用正则表达式解决什么样的字符串问题,写正则的时候都是在描述字符串规则
'''

# 2.所有匹配类符号
# 1)普通符号  -  在正则表达式中表示本身的字符就算普通符号
result = fullmatch(r'abc', 'abc')  # <re.Match object; span=(0, 3), match='abc'>
result1 = fullmatch(r'abc', '1bc')  # None 不符合
print(result)
print(result1)

# 2) .  -  匹配任意一个字符
result = fullmatch(r'.bc', '1bc')
print(result)
print(fullmatch(r'a..', 'a你好'))

# 3)\d  -  匹配任意一个数字字符
print(fullmatch(r'a\d\db', 'a97b'))

# 4)\s  -  匹配任意一个空白字符
# 空白字符 -  所有能产生空白效果的字符:空格、 \t、 \n
print(fullmatch(r'a\sb', 'a b'))
print(fullmatch(r'a\sb', 'a\tb'))
print(fullmatch(r'a\sb', 'a\nb'))

# 5)\w  -  匹配任意一个数字、字母、下划线或者中文
print(fullmatch(r'a\wb', 'a6b'))
print(fullmatch(r'a\wb', 'amb'))
print(fullmatch(r'a\wb', 'a_b'))
print(fullmatch(r'a\wb', 'a哈b'))

# 6) \D、 \S、 \W
'''
\后面跟大写字母对应的功能和\后面跟小写字母的功能相反
\D - 匹配任意一个非数字字符
\S - 匹配任意一个非空白字符
\W - 匹配任意一个非数字、字母、下划线或者中文的字符
'''
print(fullmatch(r'a\Db\Sc\We', 'albrc-e'))

# 7)[字符集]  - 匹配在字符集中任意一个字符
'''
[amx]   -  匹配a、m、x中的任意一个
[\dmn]  -  (\开头的特殊符号在中括号中还是有特殊意义)匹配任意一个数字或者m或者n 
[3-9mn]  -  (-在中括号中表示谁到谁)匹配3到9中的任意一个数字或者m或者n
[a-z]    -   匹配任意一个小写字母
[A-Z]    -   匹配任意一个小写字母
[a-zA-Z]  -  匹配任意一个字母
[\u4e00-\u9fa5]  -  匹配任意一个中文
'''

print(fullmatch(r'a[xyz]b', 'axb'))
print(fullmatch(r'a[x哈z]b', 'a哈b'))
print(fullmatch(r'a[xy1]b', 'a1b'))

print(fullmatch(r'a[ma\d]b', 'a3b'))
print(fullmatch(r'a[a-zA-Z你好呀]b', 'abb'))
print(fullmatch(r'a[a-zA-Z你好呀]b', 'aBb'))
print(fullmatch(r'a[a-zA-Z你好呀]b', 'a好b'))


print(fullmatch(r'a[\u4e00-\u9fa5A-Z]b', 'aHb'))
print(fullmatch(r'a[\u4e00-\u9fa5A-Z]\sb', 'a哈 b'))

# 注意:中括号中的-只有放在两个符号之间才能表示谁到谁,如果放在中括号的最前面或者最后面,或者中括号外部就只表示减号本身
print(fullmatch(r'a-z', 'a-z'))

# 8)[^字符集]  -  匹配不在字符集中的任意一个字符
# 注意:[]中的^,只有放在最前面才有特殊功能,如果不在最前面就算普通符号
print(fullmatch(r'a[^A-Z]b', 'a9b'))   # 中括号中表示只要不是大写字母就可以

三、匹配次数相关符号

from re import fullmatch, match

# 1. *  -  0次或者多次(任意多次)
# 匹配类符号*
print(fullmatch(r'a*b', 'b'))
print(fullmatch(r'a*b', 'aaaaaaaaab'))
print(fullmatch(r'.*b', '1m哈哈b'))
print(fullmatch(r'[A-Z]*b', 'AAAb'))

# 2. +  -   1次或者多次
print(fullmatch(r'\d+b', '1b'))
print(fullmatch(r'\d+b', '1233455b'))
print(fullmatch(r'\d+b', 'b'))  # 不匹配

# 3. ?  -   0次或者1次
print(fullmatch(r'a?b', 'b'))
print(fullmatch(r'a?b', 'ab'))

# 4. {}
'''
{N}  -   N次
{M,N}  -  M到N次
{M,}  -   至少M次
{,N}  -   最多N次
'''
print(fullmatch(r'a{3}b', 'aaab'))
print(fullmatch(r'a{3,5}b', 'aaab'))
print(fullmatch(r'a{3,5}b', 'aaaab'))
print(fullmatch(r'a{3,5}b', 'aaaaab'))
print(fullmatch(r'a{3,}b', 'aaaab'))   # 至少3个a
print(fullmatch(r'a{,2}b', 'b'))       # 不能超过2个a
print(fullmatch(r'a{,2}b', 'aaab'))    # 不匹配

# 5.贪婪和非贪婪
'''
匹配次数不确定的时候匹配模式分为贪婪和非贪婪两种,默认是贪婪的。

贪婪:在能够匹配成功的情况下,有多种匹配次数,贪婪取次数最多的那个次数。(+、*、?、{M,N}、{M,}、{,N})
非贪婪:在能匹配成功的情况下有多种匹配次数,非贪婪取次数最少的那个次数。(+?、*?、??、{M,N}?、{M,}?、{,N}?)
'''
# fullmatch(正则表达式, 字符串)  - 匹配整个字符串
# match(正则表达式, 字符串)  - 匹配字符串开头

print(match(r'a\db', 'a3b你1c好2d呀'))   # 只要开头符合规则就可以 <re.Match object; span=(0, 3), match='a3b'>

# 有三个符合条件的子串:'a1b'、'a1b你b'、'a1b你b好b'
print(match(r'a.+b', 'a1b你b好b呀'))  #  贪婪模式<re.Match object; span=(0, 7), match='a1b你b好b'>
print(match(r'a.+?b', 'a1b你b好b呀'))  # 非贪婪模式<re.Match object; span=(0, 3), match='a1b'>

print(match(r'a.?b', 'abbbb'))  # 贪婪 <re.Match object; span=(0, 3), match='abb'>
print(match(r'a.??b', 'abbbb'))  # 非贪婪 <re.Match object; span=(0, 2), match='ab'>

print(match(r'a.{1,5}b', 'a1bbbbbbbbb'))  # <re.Match object; span=(0, 7), match='a1bbbbb'>
print(match(r'a.{1,5}?b', 'a1bbbbbbbbb'))  # <re.Match object; span=(0, 3), match='a1b'>

# 练习:写正则表达式可以匹配任意一个整数字符串
# 匹配成功:'123'、'9'、'-234'、'+233’
# 匹配失败:'23m'、'--7283'、'++782'、'009'、'02'

# print(fullmatch(r'[-+1-9]\d*', '+0'))   # 不全面  如果第二位是0也可以成功
print(fullmatch(r'[-+]?[1-9]\d*', '133'))

四、分组和分支

from re import fullmatch

# 1.()  -  分组
'''
在正则表达式中可以用()将正则表达式中的部分内容括起来来表达一个整体,一个()代表一个分组。
'''

# 1)整体控制  -  以某个部分为单位对符号进行控制
# 'mn123ab563hg783mn123mn123'
print(fullmatch(r'([a-z]{2}\d{3})+', 'mn123ab563hg783mn123mn123'))

# 2)重复 -  在正则中可以通过\N来重复它前面第N个分组匹配到的结果
#  ’234-234'、'001-001'
print(fullmatch(r'(\d{3})-\1', '234-234'))
print(fullmatch(r'(\d{3})-(\d{3})-\1-\2{2}', '234-123-234-123123'))
print(fullmatch(r'([a-z]{3})-(\d{3})-\1-\2{2}', 'abc-123-abc-123123'))

# 3)捕获 -  获取匹配结果的某个部分
'''
捕获分为自动捕获和手动捕获两种,只有findall具有自动捕获的功能,其他情况需要手动捕获

findall(正则表达式, 字符串)  -  获取字符串中所有满足正则的子串
'''
from re import findall
message = '年龄: 18岁, 身高: 170, 体重: 120斤, 月薪: 3000元, 房租: 1000元'

result = findall(r'\d+', message)
print(result) # ['18', '170', '120', '3000', '1000']

result = findall(r'\d+元', message)
print(result)  #['3000元', '1000元']

# a.自动捕获 -  自动获取匹配结果中分组匹配到的内容
result = findall(r'(\d+)元', message)
print(result)  # ['3000', '1000']

# b.手动捕获 - 写额外的代码来获取匹配结果中分组匹配到的内容
result = fullmatch(r'(\d+)元', '8298元')
print(result)

# 获取整个正则对应的匹配结果:匹配对象.group()
print(result.group())  # 8298元

# 获取某个分组对应的匹配结果:匹配对象.group(分组数)
print(result.group(1))  # 8298

result = fullmatch(r'(\d{2})([a-z]{3})', '23ksk')
print(result.group())  # 23ksk
print(result.group(1))  # 23
print(result.group(2))  # ksk

message = '年龄: 18岁, 身高: 170, 体重: 120斤a, 月薪: 3000元b, 房租: 1000元'
result = findall(r'(\d+)([元斤])([a-z])', message)
print(result)  # [('120', '斤', 'a'), ('3000', '元', 'b')]

# 2. |  -  分支
'''
正则1|正则2  -  先用正则1去匹配,如果匹配成功整个正则表达式就匹配成功,如果匹配失败就用正则2来匹配
'''
# '23mns'、'34看手机'
# 方法1:
print(fullmatch(r'\d{2}[a-z]{3}|\d{2}[\u4e00-\u9fa5]{3}', '34看手机'))
# 方法2:
print(fullmatch(r'\d{2}([a-z]{3}|[\u4e00-\u9fa5]{3})', '23mns'))

print(fullmatch(r'[a-z]{5}|[\u4e00-\u9fa5]{5}', 'abmns'))

五、检测类符号

from re import fullmatch, findall,search

# 检测类符号  -  在匹配成功的情况下,检测指定的位置是否符合相应的要求(不影响字符串长度)

# 1.\b  -  检测\b所在的位置是否是单词边界
'''
单词边界:英文符号中可以区分出不同单词的符号(例如:空白符号、英文标点符号、字符串开头和结尾)
'''
print(fullmatch(r'\d{2}a\b', '23a'))
print(fullmatch(r'\d{2},\ba', '23,a'))  # <re.Match object; span=(0, 4), match='23,a'>

str1 = '123jsk5678换手机 789,89ksk898 数 899'
print(findall(r'\d+', str1))  # ['123', '5678', '789', '89', '898', '899']
print(findall(r'\b\d+', str1))  # ['123', '789', '89', '899']
print(findall(r'\d+\b', str1))  # ['789', '898', '899']
print(findall(r'\b\d+\b', str1))  # ['789', '899']

# 2. ^(中括号外面放^)  -   检测是否是字符串开头,用的时候只能放在字符串的最前面

# 3.$   -  检测是否是字符串结尾,用的时候只能放在字符串的最后面
# search(正则, 字符串)  - 获取字符串中第一个满足条件的子串
print(search(r'\d{3}', 'sgg789经济师123哈哈'))  # <re.Match object; span=(3, 6), match='789'>
print(search(r'^1[3-9]\d{9}$', '13124567123'))

# 4.转义符号  -  在正则中有特殊意义的符号前加\,让这个符号变成普通符号
# '合.234'、'块.82908'
print(fullmatch(r'[\u4e00-\u9fa5]\.\d+', '合.2345'))

# '23*89'
print(fullmatch(r'\d+\*\d+', '23*89'))

# '(MHS)'
print(fullmatch(r'\([A-Z]{3}\)', '(MHS)'))

# 5.re模块  -  模块中全是和正则表达式相关的函数
from re import fullmatch, match, search, findall, finditer, sub, split
'''
fullmatch(正则, 字符串)  - 匹配整个字符串(判断整个字符串是否符合正则描述的规则),匹配成功返回匹配对象,匹配失败返回None
match(正则, 字符串)   -  匹配字符串开头(判断字符串开头是否符合正则描述的规则),匹配成功返回匹配对象,匹配失败返回None
search(正则, 字符串)  - 匹配字符串中第一个满足条件的子串,匹配成功返回匹配对象,匹配失败返回None
findall(正则, 字符串)  -   获取字符串中所有满足正则的子串,返回值是一个列表,列表中的元素是匹配到的字符串
finditer(正则, 字符串)  -   获取字符串中所有满足正则的子串,返回值是一个迭代器,迭代器中的元素是匹配对象
sub(正则, 字符串)      -   将字符串中所有满足正则的子串作为切割点对字符串进行切割
split(正则, 字符串1, 字符串2)    -  将字符串2中所有满足正则的子串都替换成字符串1

'''
str1 = '123jsk5678换手机 789,89ksk898 数 899'
print(findall(r'\d+', str1)) # ['123', '5678', '789', '89', '898', '899']
print(list(finditer(r'\d+', str1)))
print(next(finditer(r'\d+', str1)))
print(split(r'\d+', str1))  # ['', 'jsk', '换手机 ', ',', 'ksk', ' 数 ', '']
print(sub(r'\d+|[a-zA-Z]+', 'A', str1))  # AAA换手机 A,AAA 数 A
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值