• 从零学习Python:正则表达式


    一、认识正则

    (一)什么是正则表达式

    正则表达式是一种可以让一些复杂字符串问题变得简单的工具

    正则并不是python特有语法(不属于python),所有的高级编程语言都支持正则,正则的语法通用

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

    (二)Python的re模块

    re模块是python用来支持正则表达式的一个模块,模块中包含了所有和正则相关的函数

    fullmatch(正则表达式, 字符串)

    判断正则表达式和指定的字符串是否完全匹配(判断整个字符串是否符合正则表达式所描述的规则)

    如果匹配成功返回匹配对象,匹配失败返回None

    通过示例具体理解:

    示例:判断指定的字符串是否是一个合法的手机号
    11为:每一位都是数字;第一位必须是1;第二位是3~9

    tel = input('请输入手机号:')
    
    # 普通方法
    def is_tell(num: str):
        if len(num) != 11:
            return False
        for i in num:
            if not i.isdigit():
                return False
    
        if num[0] != '1':
            return False
    
        if '3' <= num[1] <= '9':
            return True
    
        return False
    
    
    # print(is_tell(tel))
    
    # 正则表达式方法
    def is_tel2(num: str):
        from re import fullmatch
        return bool(fullmatch(r'1[3-9]\d{9}', num))
    
    
    print(is_tel2(tel))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    二、正则语法:匹配类符号

    (一)普通符号

    在正则表达式中表示符号本身的符号

    from re import fullmatch
    
    result = fullmatch(r'abc', 'abc')
    print(result)
    
    • 1
    • 2
    • 3
    • 4

    (二) . - 匹配任意一个字符

    result = fullmatch(r'a.c', 'abc')
    print(result)
    
    result = fullmatch(r'..abc', '3@abc')
    print(result)
    
    • 1
    • 2
    • 3
    • 4
    • 5

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

    result = fullmatch(r'a\dc', 'a0c')
    print(result)
    
    • 1
    • 2

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

    空白字符:能产生空白效果的字符,例如:空格、换行、水平制表符

    result = fullmatch(r'a\sc', 'a c')
    print(result)
    
    result = fullmatch(r'a\sc', 'a\nc')
    print(result)
    
    result = fullmatch(r'a\sc', 'a\tc')
    print(result)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    (五)\D - 匹配任意一个非数字字符

    result = fullmatch('a\Dc', 'abc')
    print(result)
    
    # result = fullmatch('a\Dc', 'a1c')
    # print(result)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    (六)\S - 匹配任意一个非空白字符

    # result = fullmatch(r'a\Sc', 'a c')
    # print(result)
    
    result = fullmatch(r'a\Sc', 'abc')
    print(result)
    
    • 1
    • 2
    • 3
    • 4
    • 5

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

    例如:

    """
    [abc]		-	匹配a或者b或者c
    [abc\d]		-	匹配a或者b或者c或者任意数字
    [1-9]		-	匹配1到9中的任意一个数字
    [a-z]		-	匹配任意一个小写字母
    [A-Z]		-	匹配任意一个大写字母
    [a-zA-Z]	-	匹配任意一个字母
    [a-zA-Z\d_]	-	匹配字母数字或者下划线
    [\u4e00-\u9fa5]	-	匹配任意一个中文字符
    """
    
    result = fullmatch(r'a[ande]c', 'aac')
    print(result)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    注意:[]中减号放在两个字符之间表示谁到谁(确定的方式是根据字符编码值大小确定的);如果减号不在两个字符之间,就表示一个普通的减号

    (八)[ ^ 字符集] - 匹配不在字符集中的任意一个字符

    # result = fullmatch(r'a[^ande]c', 'aac')
    # print(result)
    
    result = fullmatch(r'a[^ande]c', 'acc')
    print(result)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    \w:用于匹配字母,数字或下划线字符;
    \W:用于匹配所有与\w不匹配的字符;
    . :用于匹配除换行符之外的所有字符。

    三、匹配次数

    (一)* - 0次或多次(任意次数)

    注意:*在谁的后面控制的就是谁的次数

    """
    a*		-	0个或多个a
    \d*		-	0个或多个\d
    """
    from re import fullmatch
    
    result = fullmatch(r'a*usdcj','aaaaausdcj')
    print(result)
    
    result = fullmatch(r'\d*abc','12324234abc')
    print(result)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    (二)+ - 1次或者多次(至少一次)

    result = fullmatch(r'a+usdcj','aaaaausdcj')
    print(result)
    
    • 1
    • 2

    (三) ? - 0次或1次

    result = fullmatch(r'a?usdcj','usdcj')
    print(result)
    
    result = fullmatch(r'a?usdcj','ausdcj')
    print(result)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    (四){}

    """
    {M,N}		-	M到N次
    {M,}		-	至少M次
    {,N}		-	最多N次
    {N}			-	N次
    """
    
    result = fullmatch(r'[a-z]{3,5}123','absc123')
    print(result)
    
    result = fullmatch(r'[a-z]{3,}123','abjsfgbc123')
    print(result)
    
    result = fullmatch(r'[a-z]{,5}123','asc123')
    print(result)
    
    result = fullmatch(r'[a-z]{5}123','abjsc123')
    print(result)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    四、贪婪和非贪婪

    当匹配次数不确定的时候(*、+、?、{M,N}、{M,}、{,N}),匹配模式分为贪婪和非贪婪两种,默认是贪婪

    贪婪和非贪婪:在匹配成功的时候有多种匹配结果,贪婪取最多次数对应的匹配结果(匹配次数不确定的地方,有多种匹配方式都可以匹配成功,贪婪取最多次数,非贪婪取最少次数)

    贪婪模式:*、+、?、{M,N}、{M,}、{,N}

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

    match(正则表达式,字符串)

    判断字符串开头是否符合正则表达式的规则

    示例:

    # amb、amb计算b、amb计算bxxb
    # 贪婪模式
    result = match(r'a.+b', 'amb计算bxxbmn')
    print(result)           # 
    
    # 非贪婪模式
    result = match(r'a.+?b', 'amb计算bxxbmn')
    print(result)           # 
    
    
    # 注意:如果匹配结果只有一种可能,那么贪婪和非贪婪的结果一样
    result = match(r'a.+b', 'ambxx')
    print(result)           #  
    
    result = match(r'a.+?b', 'ambxx')
    print(result)           # 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    注意:如果匹配结果只有一种可能,那么贪婪和非贪婪的结果一样

    五、分组和分支

    (一)分组 - ()

    1)整体 - 将正则表达式中的一部分作为一个整体进行相关操作

    2)重复 - 可以在正则表达式中通过 \M 来重复它前面的第M个分组的匹配结果

    3)捕获 - 只获取正则表达式中的一部分匹配到的结果(分为手动捕获和自动捕获)

    from re import fullmatch
    from re import findall
    
    
    # '12nm34bn13jk55gh...'
    result = fullmatch(r'(\d\d[a-z]{2})+', '23mn')
    print(result)
    
    # 23m23、34j34、43h43 -   能匹配
    # 23m34、45h56   -   不能匹配
    result = fullmatch(r'(\d{2})[a-z]\1', '23m23')
    print(result)
    
    # 23jkn=jkn23
    result = fullmatch(r'(\d{2})([a-z]{3})=\2\1', '23jkn=jkn23')
    print(result)
    
    # 提取message中金额对应的数字子串
    message = '芳龄18,月入2000元,身高165,每年有5000元压岁钱,节假日爸妈给200元'
    result = findall(r'(\d+)元',message)
    print(result)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    \M 只能重复在它出现之前的分组内容,无法重复在它之后出现的内容

    # result = fullmatch(r'\d{2}\1\2=([a-z]{2})', '2323mk=mk')	# 报错!
    # print(result)
    
    • 1
    • 2

    (二)分支 - |

    正则1|正则2|正则3|… - 匹配可以和多个正则中任意一个正则匹配的字符串

    # 匹配一个字符串是三个数字或者两个小写字母
    result = fullmatch(r'\d{3}|[a-z]{2}', 'mk')
    print(result)
    
    • 1
    • 2
    • 3

    注意:如果想要正则表达式中的一部分实现多选一的效果,变化的部分用分组表示

    # a234b、amjkb
    result = fullmatch(r'a\d{3}b|a[a-z]{3}b', 'a234b')
    print(result)
    
    result = fullmatch(r'a(\d{3}|[a-z]{3})b', 'amjkb')
    print(result)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    六、转义符号

    1. 转义符号

    正则中的转义符号,就是在本身具备特殊功能或者特殊意义的符号前加’ \ ',让这个符号变成一个普通符号

    from re import fullmatch
    
    # 匹配任意一个小数对应的字符串
    result = fullmatch(r'\d+\.\d+', '234.9784')
    print(result)
    
    # +234、+3432
    result = fullmatch(r'\+\d+', '+879678')
    print(result)
    
    # (mv)、(soadhof)
    result = fullmatch(r'\([a-z]+\)', '(sxoihcoweef)')
    print(result)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2. []里面的转义符号

    单独存在有特殊意义的符号(+、*、?、.等),在[]中特殊意义会自动消失

    result = fullmatch(r'\d+[.]\d+', '234.9784')
    print(result)
    
    • 1
    • 2

    本身在[]中有特殊功能的符号,如果要表示普通符号必须加’ \ ’

    result = fullmatch(r'a[M\-N]b', 'a-b')
    print(result)
    
    result = fullmatch(r'a[MN-]b', 'a-b')
    print(result)
    
    result = fullmatch(r'a[\^MN-]b', 'a^b')
    print(result)
    
    # '\2233'
    result = fullmatch(r'\\\d+', '\92233')
    print(result)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    七、检测类符号

    检测类符号是在匹配成功的情况下,检测检测类符号所在的位置是否符合相关要求

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

    单词边界:可以将两个单词区分开的符号都是单词边界,比如:空白符号、英文标点符号、字符串开头和字符串结尾

    result = fullmatch(r'abc\b mn', 'abc mn')
    print(result)
    
    message = '203mn45,89 司机34kn;23;99mll==910,230 90='
    result = findall(r'\d+', message)  
    print(result)       # ['203', '45', '89', '34', '23', '99', '910', '230', '90']
    
    result = findall(r'\d+\b', message)		# 右边为边界的数
    print(result)       # ['45', '89', '23', '910', '230', '90']
    
    result = findall(r'\b\d+', message)		# 左边为边界的数
    print(result)       # ['203', '89', '23', '99', '910', '230', '90']
    
    result = findall(r'\b\d+\b', message)		# 左右都为边界的数
    print(result)       # ['89', '23', '910', '230', '90']
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    2. \B - 检测是否不是单词边界
    message = '203mn45,89 司机34kn;23;99mll==910,230 90='
    result = findall(r'\B\d+\B', message)		# 左右都不为边界的数
    print(result)
    
    • 1
    • 2
    • 3
    3. ^ - 检测是否是字符串开头
    message = '203mn45,89 司机34kn;23;99mll==910,230 90='
    result = findall(r'^\d+', message)
    print(result)
    
    • 1
    • 2
    • 3

    ^. {N} 提取字符串前N个字符

    message = '203mn45,89 司机34kn;23;99mll==910,230 90='
    result = findall(r'^.{5}', message)
    print(result)
    
    • 1
    • 2
    • 3
    4. $ - 检测是否是字符串结尾

    .{N}$ 提取字符串最后N个字符

    message = '203mn45,89 司机34kn;23;99mll==910,230 90='
    result = findall(r'.{5}$', message)
    print(result)
    
    • 1
    • 2
    • 3

    八、re模块常用函数

    from re import *
    
    • 1

    1.常用函数

    1) fullmatch(正则表达式, 字符串)

    完全匹配,判断整个字符串是否符合正则表达式描述的规则,匹配成功返回匹配对象,匹配失败返回空

    result = fullmatch(r'\d{3}', '234')
    print(result)
    
    • 1
    • 2

    2) match(正则表达式, 字符串)

    匹配字符串开头,判断字符串开头是否符合正则表达式描述的规则,匹配成功返回匹配对象,匹配失败返回空

    result = match(r'\d{3}', '823介绍数据库')
    print(result)
    
    • 1
    • 2

    3) search(正则表达式, 字符串)

    获取字符串中第一个能够和正则匹配的子串,能找到返回匹配对象,找不到返回空

    result = search(r'\d{3}', 'ba203还是678说')
    print(result)
    
    • 1
    • 2

    4) findall(正则表达式, 字符串)

    获取字符串中所有满足正则的子串,返回一个列表,列表中的元素是字符串

    注意:如果正则表达式中有分组,会针对分组做自动捕获(只获取分组匹配到的结果)

    result = findall(r'\d{3}', 'ba203还是678说kk0222jksn就是23311')
    print(result)
    
    • 1
    • 2

    5) finditer(正则表达式, 字符串)

    获取字符串中所有满足正则的子串,返回一个迭代器,迭代器中的元素是每个子串对应的匹配对象

    result = finditer(r'\d{3}', 'ba203还是678说kk0222jksn就是23311')
    print(result)
    print(list(result))
    
    • 1
    • 2
    • 3

    6) split(正则表达式, 字符串)

    将字符串中所有满足正则的子串作为切割点对字符串进行切割

    示例:

    将str1中的a和b作为切割点对字符串进行切割

    str1 = '123aMKnb嗑生嗑死aKKssa923b==='
    result = split(r'a|b', str1)
    print(result)       # ['123', 'MKn', '嗑生嗑死', 'KKss', '923', '===']
    
    • 1
    • 2
    • 3

    7)sub(正则表达式, 字符串1, 字符串2)

    字符串2中所有满足正则的子串都替换成字符串1

    result = sub(r'\d+', '+', 'ba203还是678说kk0222jksn就是23311')
    print(result)  # ba+还是+说kk+jksn就是+
    
    • 1
    • 2

    2.匹配对象

    result = search(r'(\d{3})([A-Z]{2})', '-=2设计师234KM222哈哈宿舍239KH')
    print(result)       # 
    
    • 1
    • 2
    1)匹配对象.group()

    直接获取整个正则表达式对应的匹配结果

    print(result.group())       # '234KM'
    
    • 1
    2)匹配对象.group(分组数)

    手动捕获某个分组对应的匹配结果

    print(result.group(1))      # '234'
    print(result.group(2))      # 'KM'
    
    • 1
    • 2
    3)匹配对象.span()

    获取匹配结果在原字符串中的位置

    print(result.span())            # (6, 11)
    print(result.span(2))           # (9, 11),这里是第二分组
    
    • 1
    • 2

    3.参考

    1)匹配忽略大小写: (?i)
    result = fullmatch(r'(?i)abc', 'AbC')
    print(result)
    
    • 1
    • 2
    2)单行匹配: (?s)
    """
    多行匹配(默认):匹配的时候.不能和换行(\n)进行匹配
    单行匹配:匹配的时候.可以和换行(\n)进行匹配
    """
    
    • 1
    • 2
    • 3
    • 4
    result = fullmatch(r'abc.123', 'abc\n123')
    print(result)       # None
    
    result = fullmatch(r'(?s)abc.123', 'abc\n123')
    print(result)       # 
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    “1688商品评论接口:打造完美电商口碑的秘密武器!“
    【Java】1608. 特殊数组的特征值---使用桶排序
    Linux命令(115)之whoami
    Vue中computed -计算属性详解
    C#事件入门
    TopSAP天融信 LINUX客户端 CentOS版安装
    git代码管理(一)
    java计算机毕业设计爱心公益网站设计与制作源码+系统+lw文档+mysql数据库+部署
    识别和定位 - 实现工业自动化及生产数字化,推动现代工业4.0
    git常用命令
  • 原文地址:https://blog.csdn.net/Yuanan_a/article/details/126258356