• Python的基础语法(十五)


    1 认识正则表达式

    1. 什么是正则表达式

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

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

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

      🍿判断指定的字符串是否是一个合法的手机号。

      11位,每一位都是数字,首位是1,第二位是3~9

      tel = input('请输入手机号:')
      
      
      # 方法一
      def is_tel(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_tel(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

      🍿提取字符串中所有的数字子串。

      str1 = '月薪: 25360元, 年龄18岁。身高:175,体重120斤。23'
      # ['25360', '18', '175', '120']
      
      # 方法一:
      result = []
      temp = ''
      for x in str1:
          if x.isdigit():
              temp += x
          else:
              if temp:
                  result.append(temp)
                  temp = ''
      
      if temp:
          result.append(temp)
      
      print(result)
      
      # 方法二:
      from re import findall
      result = findall(r'\d+', str1)
      print(result)
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
    2. Python的re模块

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

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

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

      导入模块

      from re import fullmatch
      
      • 1
    3. 正则语法

    • 匹配类符号

      符号说明
      普通符号在正则表达式中表示符号本身的符号
      .匹配任意一个字符
      \d匹配任意一个数字字符
      \s匹配任意一个空白字符
      \D匹配任意一个非数字字符
      \S匹配任意一个非空白字符
      [字符集]匹配字符集中的任意一个字符
      [ ^ 字符集]匹配不在字符集中的任意一个字符

      1)普通符号

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

      2).

      result = fullmatch(r'a.c', 'a.c')
      print(result)	#
      
      result = fullmatch(r'a.c', 'a+c')
      print(result)	#
      
      result = fullmatch(r'a..c', 'a*&c')
      print(result)	#
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

      3)\d

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

      4)\s

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

      result = fullmatch(r'a\sc', 'a c')
      print(result)	#
      
      • 1
      • 2

      5)\D

      result = fullmatch(r'a\Dc', 'a c')
      print(result)	#
      
      result = fullmatch(r'a\Dc', 'a2c')
      print(result)	#None
      
      • 1
      • 2
      • 3
      • 4
      • 5

      6)\S

      result = fullmatch(r'a\Sc', 'a2c')
      print(result)	#
      
      result = fullmatch(r'a\Sc', 'a\tc')
      print(result)	#None
      
      • 1
      • 2
      • 3
      • 4
      • 5

      7)[字符集]

      result = fullmatch(r'zhou[and]shen', 'zhouashen')
      print(result)	#
      
      result = fullmatch(r'[\u4e00-\u9fa5]', '哈')
      print(result)	#
      
      • 1
      • 2
      • 3
      • 4
      • 5

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

      🌰栗子:

      [abc]:匹配a或者b或者c

      [abc\d]、[c\dba]:匹配a或者b或者c或者任意一个数字

      [2-8]:匹配2到8中任意一个数字(前者的编码值小于后者)

      [a-z]:匹配任意一个小写字母

      [a-zA-Z]、[A-Za-z]:匹配任意一个字母

      [a-zA-Z\d_]:匹配字母数字下划线

      [\u4e00-\u9fa5]:匹配任意一个中文字符

      8)[ ^ 字符集]

      ^在最前面。

      result = fullmatch(r'[^\u4e00-\u9fa5]', '哈')
      print(result)	#None
      
      • 1
      • 2
    • 匹配次数

      符号说明
      *0次或多次(任意次数)
      +1次或者多次(至少一次)
      0次或1次
      {M,N}M到N次
      {M,}至少M次
      {,N}最多N次
      {N}N次

      1)*

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

      匹配符号*
      
      • 1
      result = fullmatch(r'a*11', 'aaa11')
      print(result)	#
      
      result = fullmatch(r'[ab]*11', 'abbaa11')
      print(result)	#
      
      • 1
      • 2
      • 3
      • 4
      • 5

      2)+

      result = fullmatch(r'[ab]+11', '11')
      print(result)	#None
      
      result = fullmatch(r'[ab]+11', 'b11')
      print(result)	#
      
      • 1
      • 2
      • 3
      • 4
      • 5

      3)?

      result = fullmatch(r'a?11', 'aa11')
      print(result)	#None
      
      • 1
      • 2

      4){}

      result = fullmatch(r'zs{3}', 'zsss')
      print(result)	#
      
      result = fullmatch(r'zs{1,2}', 'zs')
      print(result)	#
      
      result = fullmatch(r'zs{3,}', 'zssss')
      print(result)	#
      
      result = fullmatch(r'zs{2,}', 'zss')
      print(result)	#
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11

      🧈练习1:写一个正则,判断输入的内容是否是一个合法的QQ号(长度是5~12位的数字,第一位不能是0)

      qq = '123204832'
      result = fullmatch(r'[1-9]\d{4,11}', qq)
      if result:
          print('合法')
      else:
          print('不合法')
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

      🧈练习2:判断输入的内容是否是一个合法的标识符(由字母、数字下划线组成,数字不能开头)

      str1 = '_csdw2dhj'
      result = fullmatch(r'[a-zA-Z_][a-zA-Z_\d]*', str1)
      if result:
          print('合法')
      else:
          print('不合法')
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

    2 贪婪和非贪婪

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

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

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

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

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

      match(正则表达式,字符串)	判断字符串开头是否符合正则表达式描述的规则
      
      • 1
      from re import match
      
      # 贪婪模式
      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

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

    3 分组和分支

    1. 分组()

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

      result=fullmatch(r'(\d\d[A-Z]{2})+','23HJ')
      print(result)	#
      
      • 1
      • 2

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

      result = fullmatch(r'(\d{2})[A-Z]\1', '23H03')
      print(result)	#None
      
      result = fullmatch(r'(\d{2})[A-Z]\1', '23H23')
      print(result)	#
      
      result = fullmatch(r'(\d{2})([A-Z]{2})=\2\1', '23ED=ED23')
      print(result)	#
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

      注意:\M只能重复在它之前出现的内容,不能重复在它之后出现的内容。

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

      🧈提取message中金额对应的数字子串。

      from re import findall
      
      message = '我今年18岁,月薪500000元,交300元腾讯会员费,放贷2000元。'
      result = findall(r'(\d+)元', message)
      print(result)	#['500000', '300', '2000']
      
      • 1
      • 2
      • 3
      • 4
      • 5
    2. 分支|

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

      🧈匹配一个字符串是三个数字或者两个小写字母。

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

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

    4 转义符号

    1. 转义符号

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

      result = fullmatch(r'\d\+\d=\d', '1+2=3')
      print(result)	#
      
      result = fullmatch(r'\\d\+\\d=d{2}', '\d+\d=dd')
      print(result)	#
      
      • 1
      • 2
      • 3
      • 4
      • 5
    2. []里面的转义符号

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

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

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

      result = fullmatch(r'a[MN-]b', 'a-b')
      result = fullmatch(r'a[M\-N]b', 'a-b')
      result = fullmatch(r'a[M^N]b', 'a^b')
      result = fullmatch(r'a[\^MN]b', 'a^b')
      
      • 1
      • 2
      • 3
      • 4

    5 检测类符号

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

    符号说明
    \b检测是否是单词边界
    \B检测是否不是单词边界
    ^检测是否是字符串开头
    $检测是否是字符串结尾

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

    result = fullmatch(r'abc\b mn', 'abc mn')
    print(result)	#
    
    result = findall(r'\b\d+', message)
    print(result)	#['929', '999']
    
    result = findall(r'\B\d+', message)
    print(result)	#['29', '1314', '929', '99']
    
    result = findall(r'^\d+', message)
    print(result)	#['929']
    
    result = findall(r'^.{5}', message)
    print(result)	#['929zs']
    
    result = findall(r'.{5}$', message)
    print(result)	#['球,999']
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    6 re模块常用函数

    1. 常用函数

      表达式说明
      fullmatch(正则表达式,字符串)完全匹配,判断整个字符串是否符合正则表达式描述的规则,匹配成功返回匹配对象,匹配失败返回空
      match(正则表达式,字符串)匹配字符串开头,判断字符串开头是否符合正则表达式描述的规则,匹配成功返回匹配对象,匹配失败返回空
      search(正则表达式,字符串)获取字符串中第一个能够和正则匹配成功的子串,能找到返回匹配对象,找不到返回空
      findall(正则表达式,字符串)获取字符串中所有满足正则的子串,返回一个列表,列表中的元素是字符串;注意:如果正则表达式中有分组,会针对分组做自动捕获(只获取分组匹配的结果)
      finditer(正则表达式,字符串)获取字符串中所有满足正则的子串,返回一个迭代器,迭代器中的元素是每个子串对应的匹配对象
      split(正则表达式,字符串)将字符串中所有满足正则的子串作为切割点对字符串进行切割
      sub(正则表达式,字符串1,字符串2)将字符串中所有满足正则的子串都替换成字符串1

      导入模块:

      from re import *
      
      • 1
      result = fullmatch(r'\d{3}', '234')
      print(result)
      
      result = match(r'\d{3}', '823介绍数据库')
      print(result)
      
      result = search(r'\d{3}', 'ba203还是678说')
      print(result)
      
      result = findall(r'\d{3}', 'ba203还是678说kk0222jksn就是23311')
      print(result)
      
      result = finditer(r'\d{3}', 'ba203还是678说kk0222jksn就是23311')
      print(result)
      # print(next(result))
      print(list(result))
      
      str1 = '123aMKnb嗑生嗑死aKKssa923b==='
      # 将str1中的a和b作为切割点对字符串进行切割
      result = split(r'a|b', str1)
      print(result)       # ['123', 'MKn', '嗑生嗑死', 'KKss', '923', '===']
      
      result = sub(r'\d+', '+', 'ba203还是678说kk0222jksn就是23311')
      print(result)
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
    2. 匹配对象

      1)直接获取整个正则表达式对应的匹配结果:匹配对象.group()

      2)手动捕获某个分组对应的匹配结果:匹配对象.group(分组数)

      3)获取匹配结果在原字符串中的位置:匹配对象.span()

      result = search(r'(\d{3})([A-Z]{2})', '-=2设计师234KM2239KH')
      print(result)       # 
      print(result.group())       # '234KM'
      print(result.group(1))      # '234'
      print(result.group(2))      # 'KM'
      print(result.span())        # (6, 11)
      print(result.span(2)) 		#(9, 11)
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    3. 参数

      1)匹配忽略大小写(?i)写在正则表达式最前面

      result = fullmatch(r'(?i)abc', 'AbC')
      print(result)		#
      
      • 1
      • 2

      2)单行匹配(?s):匹配的时候.能和换行进行匹配

      多行匹配(默认):匹配的时候.不能和换行进行匹配

      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
  • 相关阅读:
    三十八、【进阶】最左前缀法则
    Windows 和 Linux 下后台运行 Jar包
    Excel 数据透视表教程大全之 08 创建计算字段,将销售额除以数量实现计算每种产品单价(教程含数据)
    ShowDoc后台文件上传漏洞分析 CNVD-2020-49480(CVE-2021-41745)
    pandas的append问题
    JVM 输出 GC 日志导致 JVM 卡住,我 TM 人傻了
    kafka下载|安装
    Python 基础 (七)Python的异常处理机制
    【MySQL入门到精通-黑马程序员】MySQL基础篇-函数
    VTK 标注类Widget 文字标注 vtkCaptionWidget
  • 原文地址:https://blog.csdn.net/m0_69100942/article/details/126254203