python-正则表达式与re模块

本文详细介绍了正则表达式的概念、规则及应用,包括如何利用re模块进行字符串匹配、查找、切割和替换等操作。同时,深入探讨了正则表达式的高级用法,如分组和非贪婪匹配。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、正则表达式

(1)介绍

  • 理解正则表达式:正则表达式是从左往右一个一个字符匹配的
    • 作用
      • 从大段字符串中找到符合规则的内容
      • 判断字符串是否完全符合规则
    • 定义
      • 在编写处理字符串的程序或网页时,经常有查找符合某些复杂规则的字符串的需要。
      • 正则表达式就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。

(2)规则

  • 匹配的规则:从左往右匹配,一个一个字符匹配

  • 正则表达式中的一些概念

    • 字符组:[],可以匹配出一个字符,该字符是写在中括号内的(通过ASCCI码),例子如下

      [12345_()] --> 可以匹配出:1, 2, 3, 4, 5, _, (, )
      [1-3] --> 可以匹配出:1, 2, 3
      [a-c] --> 可以匹配出:a, b, c
      [a-cA-D1-3] --> 可以匹配出:a, b, c, A, B, C, D, 1, 2, 3		
      
    • 非字符组:[^],和字符组相反

      • 例子如下

        [^0-9] --> 可以匹配出所有非数字字符
        
    • 注意:有些特殊字符进入字符组和非字符组时,会恢复原意,如[|]可以匹配|

    • 元字符

      • 转义字符:\会转义字符,想要取消某个转义,就用\\
      • . 匹配除换行符以外的任意字符
      • \w 匹配字母或数字或下划线(w–>word)
      • \s 匹配任意的空白符如\t,\n(s–>space)
      • \d 匹配数字(d–>digit)
      • \W \S \D 这3个分别和\w \s \d相反
      • \b 匹配单词的开始或结束
        • ed\b 匹配以ed结尾的单词
        • \bhe 匹配以he开头的单词
      • ^ 匹配字符串的开始
      • $ 匹配字符串的结束
      • a|b 匹配符合a规则或b规则的字符,注意先匹配a,如果符合a规则,则不检查b规则
    • 量词:用来限定字符出现的次数,所有量词只约束前面的紧贴着该量词的元字符

      • {n 前面的元字符出现n次
      • {n,} 前面的元字符至少出现n次
      • {n,m} 前面的元字符出现n-m次
      • 前面的元字符出现0或1次
      • + 前面的元字符1次或多次
      • * 前面的元字符出现0次或多次
    • 分组

      • 给几个字符加上量词约束需求时,用分组可以同时约束这几个量词,即把这几个量词分到一个组里

(3)例子

  • 匹配小数
    • \d+[.]\d+\d+\.\d+
  • 匹配小数或整数
    • \d+(\.\d+)?
    • 这里同时约束\.\d+
  • 匹配邮箱
    • [0-9a-zA-Z][\w\-\.]+@[a-zA-Z0-9\-]+(\.[0-9a-zA-Z]+)*\.[0-9a-zA-Z]{2,6}

(4)正则表达式的特点

  • 贪婪匹配:通过回溯算法
  • 非贪婪匹配/惰性匹配:在量词后面加上
  • 待匹配的字符串:asd12383248124813sda
    • 正则表达式1(贪婪匹配):\d+8
      • 匹配结果是:123832481248(先把所有数字匹配,再回溯直到找到8)
    • 正则表达式2(非贪婪匹配):\d+?8
      • 匹配结果是:1238 3248 1248(找到所有以8结尾的一串数字)

二、re模块

(1)模块简介

  • 什么是模块
    • 模块就是一组功能的集合
      • 当我们想要和某样东西打交道,而这样东西和python没有关系时,python提供了一个功能的集合,负责与这样东西打交道
      • 如os模块是与操作系统交互,可以让我们通过python操纵操作系统
    • 模块的类型:
      • 内置模块:解释器自带的
      • 第三方模块:需要我们自己安装的
      • 自定义模块:自己写的模块

(2)re模块的基本使用

  • re模块专门用来处理正则表达式

  • 查找

    • re.findall([正则表达式], [待匹配的字符串], [])

      • 匹配所有符合规则的字符串,返回的是一个列表
      • 注意:正则表达式是一个字符串
    • re.search([正则表达式], [待匹配的字符串])

      • 只匹配从左到右的第一个符合规则的字符串

      • 返回的不是真正的结果,需要通过返回的变量的group()方法获取真正的结果

      • 例子

        In [1]: import re
        
        In [2]: ret = re.search("[a-z]{2}", "12abc43jk")
        
        In [3]: ret.group()
        Out[3]: 'ab'
        
  • 字符串处理的扩展

    • 切割:re.split([正则表达式], [字符串])

      • 根据正则表达式切割

      • 注意:使用分组切割时,会保留被切割的字符串

      • 例子

        In [4]: s = "abc12de3fgh456ijk"
        
        In [5]: re.split("\d+", s)
        Out[5]: ['abc', 'de', 'fgh', 'ijk']
        
        In [6]: re.split("(\d+)", s)  # 被切割的数字也保留了
        Out[6]: ['abc', '12', 'de', '3', 'fgh', '456', 'ijk']
        
    • 替换:re.sub([正则表达式], [准备替换的内容], [待替换字符串], count=0)

      • count为替换次数,返回替换的结果

      • 例子

        In [7]: old = "asd12da3AS4444qwe"
        
        In [8]: new = re.sub("\d+", " ", old, count=3)
        
        In [9]: new
        Out[9]: 'asd da AS qwe'
        
        In [10]: new = re.sub("\d+", " ", old, count=1)
        
        In [11]: new
        Out[11]: 'asd da3AS4444qwe'
        
    • re.subn()

      • 和sub一样,只是返回的是结果及替换的次数(元组)

(3)re模块的进阶使用

  • re模块的进阶(节省时间/空间)

    • re.compile([正则表达式])

      • 节省使用正则表达式解决问题的时间

      • 编译:正则表达式编译成字节码

      • 使用compile,则在多次使用正则表达式的过程中,不会多次编译

      • 例子

        In [12]: ret = re.compile("[a-z]{3,6}")
        
        In [13]: ret
        Out[13]: re.compile(r'[a-z]{3,6}', re.UNICODE)
        
        In [14]: ret.findall("12as323qwdsa23sdsa31")
        Out[14]: ['qwdsa', 'sdsa']
        
        In [15]: ret.search("213add32djsaks2321")
        Out[15]: <_sre.SRE_Match object; span=(3, 6), match='add'>
        
        In [16]: ret.search("213add32djsaks2321").group()
        Out[16]: 'add'
        
    • re.finditer([正则表达式], [字符串])

      • 返回的是一个可迭代对象(为了节省内存)

      • 例子

        In [22]: it = re.finditer("\d{1,3}", "adda12asdas23ada23223z")
        
        In [23]: it
        Out[23]: <callable_iterator at 0x10c366860>
        
        In [24]: it.__next__().group()
        Out[24]: '12'
        
        In [25]: it.__next__().group()
        Out[25]: '23'
        
        In [26]: it.__next__().group()
        Out[26]: '232'
        
        In [27]: it.__next__().group()
        Out[27]: '23'
        
        In [28]: it.__next__().group()
        ---------------------------------------------------------------------------
        StopIteration                             Traceback (most recent call last)
        <ipython-input-28-e688ae58b280> in <module>()
        ----> 1 it.__next__().group()
        
        StopIteration: 
        
        
        # 或者
        In [29]: it = re.finditer("\d{1,3}", "adda12asdas23ada23223z")
        
        In [30]: for ele in it:
            ...:     print(ele.group())
            ...:     
        12
        23
        232
        23
        

(4)分组在re模块中的使用

  • 分组在re模块中的使用

    • 分组可以把得到的结果分别存储,我们根据需要取出结果
    In [31]: s = "<a>who</a>"
    
    In [32]: ret = re.search("<(\w+)>(\w+)<(/\w+)>", s)
    
    In [33]: ret.group()
    Out[33]: '<a>who</a>'
    
    In [34]: ret.group(1)  # 第一个分组是(\w+)
    Out[34]: 'a'
    
    In [35]: ret.group(2)  # 第二个分组是(\w+)
    Out[35]: 'who'
    
    In [36]: ret.group(3)  # 第三个分组是(/\w+)
    Out[36]: '/a'
    
    • findall的分组优先匹配原则

      In [37]: s = "<a>who</a>"
      
      In [38]: ret = re.findall(">(\w+)<", s)
      
      In [39]: ret  # 匹配到的是'>who<',但是findall优先显示分组(即(\w+))里的内容
      Out[39]: ['who']
      
      # 取消分组优先的方法:
      In [40]: s = "<a>who</a>"
      
      In [41]: re.findall(">(\w+)<", s)
      Out[41]: ['who']
      
      In [42]: re.findall(">(?:\w+)<", s)  # 加上?:即可
      Out[42]: ['>who<']		
      
    • 分组命名的语法:?P<name>

      In [43]: s = "<a>who</a>"
      
      In [44]: ret = re.search("<(?P<str1>\w+)>(?P<str2>\w+)<(?P<str3>/\w+)>", s)
      
      In [45]: ret.group()
      Out[45]: '<a>who</a>'
      
      In [46]: ret.group("str1")
      Out[46]: 'a'
      
      In [47]: ret.group("str2")
      Out[47]: 'who'
      
      In [48]: ret.group("str3")
      Out[48]: '/a'
      
    • 分组命名的一个应用

      • 分组命名可以用于匹配html的标签,例子如下

        In [49]: s1 = "<a>who</b>"
        
        In [50]: s2 = "<a>who</a>"
        
        In [51]: ret1 = re.search("<(?P<tab>\w+)>\w+</(?P=tab)>", s1)
        
        In [52]: ret2 = re.search("<(?P<tab>\w+)>\w+</(?P=tab)>", s2)
        
        In [53]: ret1  # 该字符串不符合标签配对的规则,所以没有被匹配出来
        
        In [54]: ret2
        Out[54]: <_sre.SRE_Match object; span=(0, 10), match='<a>who</a>'>
        
        • 在这个例子中,使用分组命名帮我们检查了标签的格式是否符合规则
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值