正则

本文详细讲解了正则表达式的概念、语法及各种符号的使用,包括普通字符、特殊字符类、检测符号、匹配次数和分支分组等。通过实例演示了如何在Python中使用`re`模块进行字符串匹配、替换和拆分,以及如何设置参数如大小写敏感和单行模式。
摘要由CSDN通过智能技术生成

正则

正则匹配字符

  1. 什么是正则(正则表达式)

正则是一种用来处理文本数据的一种工具。(一般用于处理复杂的文本问题)

  1. 正则的语法 - 用不同的符号来描述字符串规则
  1. 匹配类符号
  2. 检测类符号
  3. 控制次数的符号
  4. 分组和分支
  5. 其他常用参数

fullmatch(正则表达式, 字符串) - 检测字符串是否符合正则表达式描述的规则,如果不符合返回None

  1. 匹配类符号 - 一个符号对应字符串的一个字符

1)普通字符 - 特殊符号以外的字符就是普通字符

普通字符在正则中表示这个符号本身

from re import fullmatch
re_str = 'abc'     # 需要一个长度是3的字符串,并且第一个字符是a, 第二个字符是b, 第三个字符是c
print(fullmatch(re_str, 'abc'))

2). - 匹配一个任意字符

re_str = 'a.c'    # 需要一个长度是3的字符串, 并且第一个字符是a, 最后一个字符是c,中间是任意字符
print(fullmatch(re_str, 'a胡c'))

3)\d - 匹配任意一个数字字符

re_str = r'ab\d'    # 一个长度是3的字符串,ab后面是一个任意数字
print(fullmatch(re_str, 'ab3'))

*4)\w - 匹配任意一个数字、字母或者下划线(基于ASCII码)

re_str = r'\w123'
print(fullmatch(re_str, '好123'))

5)\s - 匹配任意一个空白字符

空白字符 - 空格、\t、\n

re_str = r'123\sabc'
print(fullmatch(re_str, '123 abc'))

6)\D、\S、\W

\D - 匹配任意一个非数字字符
\S - 匹配任意一个非空白字符

print(fullmatch(r'abc\S123\D', 'abcM123='))

7)[字符集] - 匹配字符集中的任意一个字符

[ab12] - 匹配a、b、1或者2中任意一个字符
[ab\d]、[\dab]、[a\db]、[ab0123456789] - 匹配a、b、或者0到9中任意一个字符
[0-9] - 匹配0到9中任意一个字符
[56789]、[5-9] - 匹配5到9中任意一个字符
[a-z] - 匹配任意一个小写字母
[A-Z] - 匹配任意一个大写字母
[a-zA-Z] - 匹配任意一个字母
[a-zA-Z\d_] - 匹配任意一个字母、数字、下划线
[\u4e00-\u9fa5] - 匹配任意一个中文

注意:如果[]中-在两个字符之间表示范围,如果-不在两个字符之间,它不具备特殊功能表示这个符号本身, -在[]外面也是普通符号

re_str = r'a[xyz]b'
print(fullmatch(re_str, 'ayb'))

print(fullmatch(r'abc[2-5]', 'abc4'))

print(fullmatch(r'[\u4e00-\u9fa5]abc', '好abc'))
# print(fullmatch(r'[z-a]abc', 'wabc'))   # 报错

print(fullmatch(r'[ac-]123', '-123'))

8)[^字符集] - 匹配除了字符集以外的任意一个字符

print(fullmatch(r'[^axy]123', 'k123'))
print(fullmatch(r'[^a-zA-Z]123', '-123'))

注意:[]里面,只有放在最前面才有特殊意义,在其他位置表示本身

print(fullmatch(r'[a-z^]123', '^123'))

检测符号

from re import fullmatch, findall, search

检测类符号在正则中不会影响字符串长度,它们的作用是在匹配成功以后检测检测类符号所在的位置是否符号要求

  1. \b - 检测是否是单词边界

单词边界 - 凡是能够将两个单词区分开的所有的符号,主要有:空白、标点符号、字符串开头和字符结尾

re_str = r'abc \b123'
print(fullmatch(re_str, 'abc 123'))

re_str = r'abc\b.123'
print(fullmatch(re_str, 'abc,123'))

str1 = '数据集,890,shs323节省时间34jsj 922 失敬失8敬283'
result = findall(r'\b\d+\b', str1)
print(result)
  1. \B - 检测是否不是单词边界
result = findall(r'\B\d+\B', str1)
print(result)
  1. ^ - 检测是否是字符串开头([]外面)
  2. $ - 检测是否是字符串结尾([]外面)
# re_str = r'^\dabc'
re_str = r'\dabc$'
print(findall(re_str, '7abc啥时间2abc数据9abc是6abc'))

匹配次数

from re import fullmatch, search, findall
import requests
  1. * - 匹配0次或多次

a* - 匹配0个或者多个a
.* - 匹配0个或者多个任意字符
\d* - 相当于任意多个\d
[xyz]* - 相当于任意多个[xyz]

re_str = r'a*123'
print(fullmatch(re_str, 'aaaaaa123'))

re_str = r'.*123'
print(fullmatch(re_str, 'asc123'))

re_str = r'\d*abc'
print(fullmatch(re_str, '78908887abc'))

re_str = r'[xyz]*123'
print(fullmatch(re_str, 'xxyz123'))
  1. + - 1次或者多次
  2. ? - 0次或者1次
  3. {}

{N} - 匹配N次
{M,N} - 匹配M~N次
{,N} - 匹配0~N次(最多N次)
{M,} - 匹配至少M次

print(fullmatch(r'\d{3}abc{5}', '722abccccc'))
print(fullmatch(r'\d{3,5}abc', '72126abc'))
print(fullmatch(r'\d{,2}abc', '23abc'))
print(fullmatch(r'\d{2,}abc', '2231abc'))
  1. 贪婪和非贪婪

贪婪和非贪婪模式是在匹配次数不确定的时候才会出现:*、+、?、{M,N}、{,N}、{M,}
贪婪和非贪婪:在能够匹配成功的情况下,如果对应的匹配次数有多种,贪婪模式选最多的那个次数,非贪婪选最少的那个次数。

贪婪:、+、?、{M,N}、{,N}、{M,}
非贪婪:
?、+?、??、{M,N}?、{,N}?、{M,}?

print(search(r'\d{3}', 'shsj234色即是空889====902'))    # <re.Match object; span=(4, 7), match='234'>

re_str = r'a.+b'
print(search(re_str, '试试amnbxyzb是计算机数据'))    # <re.Match object; span=(2, 10), match='amnbxyzb'>

re_str = r'a.+?b'
print(search(re_str, '试试amnbxyzb是计算机数据'))    # <re.Match object; span=(2, 6), match='amnb'>

re_str = r'a.+b'
print(search(re_str, '试试amnbxyz是计算机数据'))    # <re.Match object; span=(2, 6), match='amnb'>


response = requests.get('http://api.tianapi.com/txapi/ncovabroad/index?key=c9d408fefd8ed4081a9079d0d6165d43')
result = findall(r'"provinceName":"([\u4e00-\u9fa5]+?)"', response.text)
print(result)

分支和分组

from re import fullmatch, findall

1.分组 - ()

应用一:将正则表达式中的一部分用()括起来表示一个整体,然后进行整体相关操作

# hj78hu23kk90
re_str = r'([a-zA-Z]{2}\d\d){3}'
print(fullmatch(re_str, 'hj78hu23kk90'))

应用二:通过\M来重复它前面第M个分组匹配到的内容

# mn123mn、xy123xy
re_str = r'([a-z]{2})123\1'
print(fullmatch(re_str, 'mn123mn'))

re_str = r'(\d{2})([A-Z]{3})\1\2'
print(fullmatch(re_str, '12MNA12MNA'))

# re_str = r'(\d{2})\2([A-Z]{3})\1'
# print(fullmatch(re_str, '12MNHMNH12'))    # 报错!

re_str = r'(\d{2})([A-Z]{3})\1{2}\2'
print(fullmatch(re_str, '12KAM1212KAM'))

应用三:捕获(获取结果的时候只取某个分组对应的内容)

re_str = r'[a-z](\d{3})'
result = findall(re_str, 'hsjs234失敬失敬你a8393sjjk9901啥时间---234看看嘛238')
print(result)
  1. 分支 - |

正则1|正则2

|相当于或者

# abc123、abcMN
re_str = r'abc\d{3}|abc[A-Z]{2}'
print(fullmatch(re_str, 'abcMN'))

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

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

re模块

from re import *
  1. compile(正则表达式) - 创建正则表达式对象
re_obj = compile(r'\d{3}')
print(re_obj.fullmatch('384'))

print(fullmatch(r'\d{3}', '234'))
  1. 匹配相关方法

1)fullmatch(正则表达式, 字符串) - 完全匹配,判断整个字符串是否符合正则表达式描述的规则。如果不符合返回None,如果符合返回匹配对象

2)match(正则表达式, 字符串) - 匹配开头,判断字符串开头是否符合正则表达式描述的规则。如果不符合返回None,如果符合返回匹配对象

re_str = r'[a-z]{3}'
print(fullmatch(re_str, 'hsm'))
print(match(re_str, 'mks结束的发就好为34'))

3)匹配对象

re_str = r'((\d{2})([A-Z]{3}))'
result = match(re_str, '23KLA失敬失敬')
print(result)    # <re.Match object; span=(0, 5), match='23KLA'>

a.
匹配对象.group() / 匹配对象.group(0) - 获取整个正则匹配到的内容
匹配对象.group(N) - 获取正则表达式第N个分组匹配到的内容

print(result.group())     # '23KLA'
print(result.group(1))    # '23KLA'
print(result.group(2))      # '23'
print(result.group(3))      # 'KLA'

b.
匹配对象.span() / 匹配对象.span(0) - 获取整个正则匹配到的内容在原字符串中的位置信息(开始下标和结束下标)
匹配对象.span(N) - 获取正则表达式第N个分组匹配到的内容在原字符串中的位置信息

print(result.span())
print(result.span(3))

c.匹配对象.string - 获取原字符串

print(result.string)   # '23KLA失敬失敬'
  1. 查找相关方法
  1. search(正则表达式, 字符串) - 在字符串中搜索第一个满足正则表达式的字符串。如果找不到返回None,找到了返回匹配对象
print(search(r'\d{3}', '试试234节省时间988开始时间210'))    # <re.Match object; span=(2, 5), match='234'>
  1. findall(正则表达式, 字符串) - 获取字符串中所有满足正则表达式的子串。返回值是列表,如果找不到返回空列表
print(findall(r'\d{3}', '试试234节省时间988开始时间210'))    # ['234', '988', '210']
print(findall(r'\d{3}[\u4e00-\u9fa5]', '试试234节省时间988开始时间210mn'))   # ['234节', '988开']
print(findall(r'(\d{3})[\u4e00-\u9fa5]', '试试234节省时间988开始时间210mn'))   # ['234', '988']
print(findall(r'\d{3}-[a-z]{2}', '啥时间233-ks试试,892-mk啥,sjs2912-op'))  # ['233-ks', '892-mk', '912-op']
print(findall(r'(\d{3})-([a-z]{2})', '啥时间233-ks试试,892-mk啥,sjs2912-op'))   # [('233', 'ks'), ('892', 'mk'), ('912', 'op')]
print(findall(r'(\d[a-z]){3}', '是计算机上8m9l0b,s数据是8a0p1k'))    # ['0b', '1k']
  1. finditer(正则表达式, 字符串) - 获取字符串中所有满足正则表达式的子串。返回一个迭代器,迭代器中的元素是匹配对象
result = finditer(r'(\d{3})-([a-z]{2})', '啥时间233-ks试试,892-mk啥,sjs2912-op')
# print([x.group() for x in result])    # ['233-ks', '892-mk', '912-op']
# print([x.group(1) for x in result])     # ['233', '892', '912']
print([x.group(2) for x in result])       # ['ks', 'mk', 'op']
  1. sub(正则表达式, 字符串1, 字符串2) - 将字符串2中所有满足正则的子串全部替换成字符串
str1 = 'how are you? I am fine, Thank you!'
result = sub(r'you', 'me', str1)
print(result)    # how are me? I am fine, Thank me!

str1 = 'how are you? I am fine, Thank you!'
result = sub(r'you|I', 'me', str1)
print(result)   # how are me? me am fine, Thank me!

result = sub(r'傻[\s/,.\\]*[b瓜]|f\s*u\s*c\s*k|操', '*', r'我操, 你是傻    /b吗?F u c k')
print(result)
  1. split(正则表达式, 字符串) - 将字符串中所有满足正则表达式的子串作为切割点对字符串进行切割
result = split(r'[-+]', '试试-j234ss+skskj-健康是390福+世纪东2方看019计算机')
print(result)

result = split(r'\d+', '试试-j234ss+skskj-健康是390福+世纪东2方看019计算机')
print(result)

转义符号和参数

from re import fullmatch, I, S

1.转义符号 - 将在正则中有特殊功能或者意义的符号变成一个普通字符

\具有特殊意义的符号: .、+、*、…

re_str = r'\d{2}\.\d{2}'
print(fullmatch(re_str, '23.34'))

re_str = r'\\dabc\+'
print(fullmatch(re_str, '\dabc+'))

re_str = r'\(\d{2}\)'
print(fullmatch(re_str, '(23)'))

将独立存在具备特殊功能的符号放在[]里面,这个符号的功能会自动消失

特别注意符号在[]里面也有特殊功能的情况,比如:^、-、[、]

re_str = r'\d{2}[.+?*(\-)|$^\]]\d{2}'
print(fullmatch(re_str, '23]34'))
  1. 常用参数

1)忽略大小写

默认不忽略大小写

re_str = r'123[a-z]'
print(fullmatch(re_str, '123k'))   # <re.Match object; span=(0, 4), match='123k'>
print(fullmatch(re_str, '123M'))   # None

方法一: r’(?i)正则表达式’

re_str = r'(?i)123[a-z]'
print(fullmatch(re_str, '123k'))   # <re.Match object; span=(0, 4), match='123k'>
print(fullmatch(re_str, '123M'))    # <re.Match object; span=(0, 4), match='123M'>

方法二:

re_str = r'123[a-z]'
print(fullmatch(re_str, '123M', flags=I))    # <re.Match object; span=(0, 4), match='123M'>
  1. 单行匹配

多行匹配(默认) - 表示任意字符的.不能和\n(换行符)进行匹配

re_str = r'abc.123'
print(fullmatch(re_str, 'abc\n123'))    # None

单行匹配 - 表示任意字符的.可以和\n(换行符)进行匹配

方法一:

re_str = r'(?s)abc.123'
print(fullmatch(re_str, 'abc\n123'))   # <re.Match object; span=(0, 7), match='abc\n123'>

方法二:

re_str = r'abc.123'
print(fullmatch(re_str, 'abc\n123', flags=S))   # <re.Match object; span=(0, 7), match='abc\n123'>
  1. 既忽略大小写又单行匹配
re_str = r'(?is)abc.123'
print(fullmatch(re_str, 'ABC\n123'))    # <re.Match object; span=(0, 7), match='ABC\n123'>


re_str = r'abc.123'
print(fullmatch(re_str, 'ABC\n123', flags=I | S))   # <re.Match object; span=(0, 7), match='ABC\n123'>

作业

利用正则表达式完成下面的操作:

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

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

  1. 能够完全匹配字符串“c:\rapidminer\lib\plugs”的正则表达式包括( ABC)
    A. “c:\rapidminer\lib\plugs”
    B. “c:\rapidminer\lib\plugs”
    C. “(?i)C:\RapidMiner\Lib\Plugs” ?i:将后面的内容的大写变成小写
    D. “(?s)C:\RapidMiner\Lib\Plugs” ?s:单行匹配
  2. 能够完全匹配字符串“back”和“back-end”的正则表达式包括( A C)
    A. “\w{4}-\w{3}|\w{4}”
    B. “\w{4}|\w{4}-\w{3}”
    C. “\S±\S+|\S+”
    D. “\w*\b-\b\w*|\w*”
  3. 能够完全匹配字符串“go go”和“kitty kitty”,但不能完全匹配“go kitty”的正则表达式包括(CD)
    A. “\b(\w+)\b\s+\1\b”
    B. “\w{2,5}\s*\1”
    C. “(\S+) \s+\1”
    D. “(\S{2,5})\s{1,}\1”
  4. 能够在字符串中匹配“aab”,而不能匹配“aaab”和“aaaab”的正则表达式包括( BC)
    A. “a*?b”
    B. “a{,2}b”
    C. “aa??b”
    D. “aaa??b”
二、编程题

1.用户名匹配

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

​ 2.不能以数字开头

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

re_str = r'(?i)[a-z_][a-z\d_]{5,15}'
  1. 密码匹配

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

​ 2.必须以字母开头

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

re_str = r'(?i)[a-z][^!@#¥%^&*]{5,11}'
  1. ipv4 格式的 ip 地址匹配
    提示: IP地址的范围是 0.0.0.0 - 255.255.255.255
re_str = r'(([0-255])\.){3}\2'
  1. 提取用户输入数据中的数值 (数值包括正负数 还包括整数和小数在内) 并求和
例如:“-3.14good87nice19bye” =====> -3.14 + 87 + 19 = 102.86
result = split(r'[a-z]','-3.14good87nice19bye')
count = 0
for x in result:
    if x != '':
        count += float(x)
print(count)
  1. 验证输入内容只能是汉字

    def is_chinese_character(str1):
        result = fullmatch(r'[\u4e00-\u9fa5]',str1)
        if result:
            print(str1,'是汉字')
        else:
            print(str1, '不是汉字')
    
    is_chinese_character('颖')
    
  2. 匹配整数或者小数(包括正数和负数)

    re_str = '[-]?[0-9]*(|\.[0-9]+)'
    print(fullmatch(re_str,'-0.03'))
    
  3. 验证输入用户名和QQ号是否有效并给出对应的提示信息

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

    def check(account,qq):
        re_account = r'(?i)[a-z_\d]{6,20}'
        re_qq = r'[^34]+'
        result_account = fullmatch(re_account,account)
        result_qq = fullmatch(re_qq,qq)
        if result_account and result_qq:
            print('用户名和qq号都合法')
        elif (not result_account) and result_qq:
            print('用户名非法,qq号合法')
        elif result_account and (not result_qq):
            print('用户名合法,qq号非法')
        else:
            print('用户名和qq号都非法')
    
    account = input('请输入用户名:')
    qq = input('请输入qq号:')
    check(account, qq)
    
  4. 拆分长字符串:将一首诗的中的每一句话分别取出来

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

poem = '窗前明月光,疑是地上霜。举头望明月,低头思故乡。'
print(split(r'[,。]',poem)[:-1])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值