• 014-正则表达式


    正则表达式

    一、正则

    正则表达式是一种可以让复杂的字符串问题变得简单的工具;正则不独属于python,几乎所有的高级语言都支持正则表达式;

    二、python的re模块

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

    1、re模块相关函数
    from re import 函数名
    fullmatch(正则表达式,字符串)--判断正则表达式和指定的字符串是否完全匹配                            		匹配成功返回匹配对象,匹配失败返回空None
    match(正则表达式,字符串) - 判断字符串开头是否符合正则表达式描述的规则
                            匹配成功返回匹配对象,失败返回空
    search(正则表达式,字符串)--获取字符串中第一个能够和正则匹配成功的子串
                            找到匹配对象返回匹配对象,失败返回空
    findall(正则表达式,字符串)--获取字符串中所有满足正则的子串,返回一个列表,列表中的元素都是字符串
         注意:如果正则表达式中有分组,会针对分组做自动捕获(只获取分组匹配到的结果)              
    finditer(正则表达式,字符串)--获取字符串中所有满足正则的子串,返回一个迭代器,
    						迭代器中的元素是匹配结果
    split(正则表达式,字符串)--将字符串中所有满足正则的子串作为切割点进行切割
    sub(正则表达式,新字符串,旧字符串) -- 将旧字符串中所有满足正则的子串都替换成新字符串
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    2、匹配对象
    2.1 直接获取整个正则表达式对应的匹配结果
    匹配对象.group()
    
    • 1
    2.2 手动捕获某个分组对应的结果
    匹配对象.group(分组数)
    
    • 1
    2.3 获取匹配结果在原字符串中的位置
    匹配对象.span()
    
    • 1
    3、参数
    3.1 匹配忽略字母大小写
    (?i)
    from re import fullmatch
    print(fullmatch(r'(?i)abc', 'aBc'))
    
    • 1
    • 2
    • 3
    3.2 单行匹配

    单行匹配:匹配的时候’.‘能和换行’\n’进行匹配

    多行匹配:匹配的时候’.‘不能和换行’\n’进行匹配

    (?s)
    from re import fullmatch
    print(fullmatch(r'(?s)abc.123', 'abc\n123'))  # 单行匹配成功
    print(fullmatch(r'abc.123', 'abc\n123'))  # 多行匹配 None
    
    • 1
    • 2
    • 3
    • 4

    三、正则语法 - 匹配类符号

    1、普通符号 - 在正则表达式中表示符号本身的符号
    print(fullmatch(r'abc', 'abcdefr'))
    
    • 1
    2、. - 匹配任意字符
    print(fullmatch(r'a.c', 'avc'))
    
    • 1
    3、\d - 匹配任意一个数字字符
    print(fullmatch(r'a\dc', 'a1c'))
    
    • 1
    4、\D - 匹配任意一个非数字字符
    print(fullmatch(r'a\Dc', 'a2c')) # None
    
    • 1
    5、\s - 匹配任意一个空白字符
    print(fullmatch(r'a\sv', 'a v'))
    print(fullmatch(r'a\sv', 'a\tv'))
    
    • 1
    • 2
    6、\S - 匹配任意一个非空白字符
    print(fullmatch(r'a\Sv', 'a\tv')) # None
    
    • 1
    7、\w : 匹配任意单个a-zA-Z0-9_汉字 或表示为[a-zA-Z0-9_]
    8、\W : 匹配任意单个非a-zA-Z0-9_汉字别的任何 或表示为[^a-zA-Z0-9_]
    9、[字符集] - 匹配字符集中的任意一个字符 字符集中的顺序任意
    [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] -   匹配任意一个中文字符
    注意:中括号[]中减号放在两个字符之间,表示区间,表示谁到谁(确定的方式是根据字符编码值的大小确定的)
         如果减号不在两个字符之间,就表示一个普通的符号
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    10、[^字符集] - 匹配不在字符集中的任意一个字符
    print(fullmatch(r'a[^\u4e00-\u9fa5]b', 'a一b')) # None
    print(fullmatch(r'a[^\u4e00-\u9fa5]b', 'avb'))  
    # 
    
    • 1
    • 2
    • 3

    四、匹配次数

    方法次数示例
    *0次或者多次(任意次数)
    *放在谁的后面就控制谁的次数
    a* - 0个或者多个a
    \d* - 0个或者多个数字
    print(fullmatch(r'a*1', 'aaa1')) # 匹配成功
    +1次或者多次(至少一次)print(fullmatch(r'a+122', '122')) # None
    print(fullmatch(r'a+122', 'a122'))
    0次或者1次print(fullmatch(r'a?122', 'a122')) print(fullmatch(r'a?122', '122'))
    {}{M,N} M到N次
    {M,} - 至少M/
    {,N} - 最多N次
    {N} - N次
    练习
    # 练习:写一个正则,判断输入的内容是否是一个合法的QQ号(长度是5~12位的数字,第一位不能是0)
    qq=input('请输入qq号:')
    print(bool(fullmatch(r'[1-9]\d{4,11}', qq)))
    
    • 1
    • 2
    • 3
    练习
    # 练习:判断输入的内容是否是一个合法的标识符(由字母、数字下划线组成,数字不能开头)
    bsf='_12fds'
    print(bool(fullmatch(r'[a_zA-Z_][a-zA-Z\d_]*',bsf)))
    
    • 1
    • 2
    • 3

    五、贪婪和非贪婪

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

    贪婪和非贪婪:在匹配成功的时候有多种匹配结果,贪婪取最多次数对应的匹配结果,非贪婪取最少次数对应的匹配结果

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

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

    # 结果  amb 、amb计算b 、 amb计算bxxb
    print(match(r'a.+b', 'amb计算bxxbmn'))
    #
    print(match(r'a.+?b', 'amb计算bxxbmn'))
    # 
    
    • 1
    • 2
    • 3
    • 4
    • 5

    六、分组和分支

    1、分组 - ()

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

    from re import fullmatch,findall
    # '12SV34DS23AC...'
    str2='12SV34DS23AC'
    print(fullmatch(r'(\d\d[A-Z]{2})+', str2))
    
    • 1
    • 2
    • 3
    • 4

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

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

    from re import fullmatch
    # 23m23 98k98  32f32
    print(fullmatch(r'(\d{2})[a-z]\1', '23m23'))
    # 23mgi=mgi23
    print(fullmatch(r'(\d{2})([a-z]{3})=\2\1', '34hjl=hjl34'))
    
    • 1
    • 2
    • 3
    • 4
    • 5

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

    from re import findall
    message='我今年18岁,月薪50000元,身高180,体重78公斤,8块腹肌。每年交308元的腾讯会员费。房贷每月3008元,车贷每月2208元。'
    result=findall(r'(\d+)元',message)
    print(result)
    
    • 1
    • 2
    • 3
    • 4
    2、分支
    正则1|正则2|正则3|...  -  匹配可以和多个正则中任意一个匹配的字符串
    
    • 1

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

    # a21b、amlsb  a开头b结尾 中间两个数字或者三个字母
    from re import fullmatch,findall
    print(fullmatch(r'a(\d{2}|[a-z]{3})b', 'a32b'))
    print(fullmatch(r'a(\d{2}|[a-z]{3})b', 'avfgb'))
    print(findall(r'a(\d{2}|[a-z]{3})b', 'avfgb'))
    
    • 1
    • 2
    • 3
    • 4
    • 5

    七、转义符号

    1、转义符号

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

    from re import fullmatch
    result=fullmatch(r'\d+\.\d+','23.122')
    print(result)
    print(fullmatch(r'\([a-z]+\)', '(dfa)'))
    
    • 1
    • 2
    • 3
    • 4
    2、[]里面的转义符号

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

    from re import fullmatch
    result = fullmatch(r'\d+[.+*?]\d+', '433?444')
    print(result)
    
    • 1
    • 2
    • 3

    本身在中括号中有特殊功能的符号(-、^),如果表示普通符号必须加\

    八、检测类符号

    检测符号并不影响匹配,只是对匹配的符号进行筛选

    1、 \b 检测是否是单词边界

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

    print(fullmatch(r'abc\b mn', 'abc mn'))
    
    • 1
    2、 \B 检测是否不是单词边界
    3、 ^ 检测是否是字符串开头
    message='dfa123 四级的ewr235 ewr9=='
    print(findall(r'^.{5}', message)) # ['dfa12']
    
    • 1
    • 2
    4、 $ 检测是否是字符串结尾
    message='dfa123 四级的ewr235 ewr9=='
    print(findall(r'.{5}$', message)) # ['wr9==']
    
    • 1
    • 2

    正则表达式练习题

    一、不定项选择题

    1. 能够完全匹配字符串"(010)-62661617"和字符串"01062661617"的正则表达式包括( ABD)

      A. r"\(?\d{3}\)?-?\d{8}"
      B. r"[0-9()-]+"
      C. r"[0-9(-)]*\d*" #(-)是一个整体,代表()
      D.r"[(]?\d*[)-]*\d*"

    2. 能够完全匹配字符串"back"和"back-end"的正则表达式包括(ABCD )
      A. r'\w{4}-\w{3}|\w{4}' # \w 匹配任意单个a-zA-Z0-9_汉字
      B. r'\w{4}|\w{4}-\w{3}'
      C.r'\S+-\S+|\S+' #\S 非空字符
      D. r'\w*\b-\b\w*|\w*'

    3. 能够完全匹配字符串"go go"和"kitty kitty",但不能完全匹配“go kitty”的正则表达式包括(AD)
      A.r'\b(\w+)\b\s+\1\b' # \s 匹配任何一个空白字符
      B. r'\w{2,5}\s*\1' # 没有分组 正确写法 :r'(\w{2,5})\s*\1'
      C. r'(\S+) \s+\1' # 中间有空格 正确写法 :r'(\S+)\s+\1' 或者 r'(\S+) +\1'
      D. r'(\S{2,5})\s{1,}\1'

    4. 能够在字符串中匹配"aab",而不能匹配"aaab"和"aaaab"的正则表达式包括(BC )
      A. r"a*?b"
      B. r"a{,2}b"
      C. r"aa??b" # ab、aab 可以匹配
      D. r"aaa??b" # aaab 能匹配 aaaab不能匹配

    二、编程题

    1.用户名匹配

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

    ​ 2.不能以数字开头

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

    from re import fullmatch
    name='f324_dska2'
    result=fullmatch(r'[a-zA-Z_][a-zA-Z0-9_]{5,15}', name)
    # result=fullmatch(r'[a-zA-Z_][a-zA-Z\d_]{5,15}', name)
    if result:
        print('合法')
    else:
    	print('不合法')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    1. 密码匹配

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

    ​ 2.必须以字母开头

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

    from re import fullmatch
    password = 'sdfs213'
    result=fullmatch(r'[a-zA-Z][^!@#$%^&*]{5,11}', password)
    if result:
        print(password,'合法')
    else:
        print(password,'不合法')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1. ipv4 格式的 ip 地址匹配
      提示: IP地址的范围是 0.0.0.0 - 255.255.255.255
    from re import fullmatch
    ip = '255.256.255.255'
    # 分段 从数字的不同位数考虑 0-9  10-99 100-199 200-249 250-255
    result=fullmatch(r'((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.){3}(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])',ip)
    if result:
        print(ip,'合法')
    else:
        print(ip,'不合法')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    1. 提取用户输入数据中的数值 (数值包括正负数 还包括整数和小数在内) 并求和
    例如:“-3.14good87nice19bye” =====> -3.14 + 87 + 19 = 102.86
    
    • 1
    from re import findall
    num='-3.14good87nice19bye'
    list1=findall(r'-?\d+\.?\d+',num)
    total=sum(float(i) for i in list1)
    print(total)  # 102.86
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 验证输入内容只能是汉字
    from re import fullmatch
    text=input('请输入内容:')
    print(fullmatch(r'[\u4e00-\u9fa5]', text))
    
    • 1
    • 2
    • 3
    1. 匹配整数或者小数(包括正数和负数)
    from re import fullmatch
    # 整数正则 [-+]?(0|[1-9]\d*)
    # 小数正则 [-+]?(0|[1-9]\d*)\.\d+
    # 数字正则  [-+]?(0|[1-9]\d*)(\.\d+)?
    num=input('请输入数字:')
    print(fullmatch(r'[-+]?(0|[1-9]\d*)(\.\d+)?',num))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 验证输入用户名和QQ号是否有效并给出对应的提示信息

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

    from re import fullmatch
    name='lili_012'
    QQ='1532141423'
    print(fullmatch(r'[a-zA-Z0-9_]{6,20}', name))
    print(fullmatch(r'[1-9]\d{4,11}', QQ))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. 拆分长字符串:将一首诗的中的每一句话分别取出来

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

    from re import split
    poem = '窗前明月光,疑是地上霜。举头望明月,低头思故乡。'
    result=split(r',|。',poem)
    for i in result:
        print(i)
    # 窗前明月光
    # 疑是地上霜
    # 举头望明月
    # 低头思故乡
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  • 相关阅读:
    c++网络编程
    使用 Python脚本在3DMAX中加载图像和读取图像中的像素值
    oracle使用小结
    水果FL Studio/Cubase/Studio one音乐宿主软件对比
    MySQL(高级、面试) —— (MySQL优化 二)Explain 优化MySQL索引
    浮点型数字
    【智能优化算法】基于多元宇宙算法求解多目标经济联合排放调度优化问题
    如何把一个空项目变成SpringBoot项目
    电脑录屏快捷键是什么?电脑录屏是什么键
    我用Axure制作了一款火影小游戏 | PM老猫
  • 原文地址:https://blog.csdn.net/qq_44087994/article/details/126255555