zoukankan      html  css  js  c++  java
  • Python--re模块

    正则表达式

    正则表达式:一种字符串匹配的规则

    字符组

    字符组 : [字符组]
    在同一个位置可能出现的各种字符组成了一个字符组,在正则表达式中用[]表示
    字符分为很多类,比如数字、字母、标点等等。
    假如你现在要求一个位置"只能出现一个数字",那么这个位置上的字符只能是0、1、2...9这10个数之一。
    正则 待匹配字符 匹配结果 说明
    [0123456789] 6 True 在一个字符组里枚举合法的所有字符,字符组的任意一个字符和"待匹配字符"相同都视为可匹配
    [0123456789] a False 由于字符组中没有“a”,所以不能匹配
    [0-9] 7 True 匹配0-9中的任意数字;等于[0123456789]
    [a-z] s True 匹配a-z中任意小写字母。
    [A-Z] B True 匹配A-Z中任意大写字母。
    [0-9a-zA-Z] e True 匹配任意数字、大小写字母。

    字符

    元字符 匹配内容
    . 匹配除换行符以外的任意字符
    w 匹配字母或数字或下划线
    s 匹配任意的空白符:空格、tab、换行;等于[f ]
    d 匹配数字;等于[0-9]
    W 匹配非字母或数字或下划线,也就是说除了字母、数字、下划线以外的
    S 匹配非任意的空白符,也就是说除了空格、tab、换行以外的;等于[^ f ]
    D 匹配非数字,也就是说除了数字以外的
    匹配一个制表符,tab
    匹配一个换行符
    ^ 匹配字符串以什么开头的
    $ 匹配字符串以什么结尾的
    a|b 匹配字符a或者字符b,| 或者的关系
    () 匹配括号内的表达式,也表示一个组
    [...] 匹配字符组中的字符
    [^...] 匹配非字符组中的所有字符
     匹配一个单词的边界

    注意这三种的结果都表示匹配所有:[dD]、[sS]、[wW]

    量词

    量词 用法说明
    * 重复零次或者多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等价于{0,}。
    + 重复一次或者多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
    ? 重复零次或者一次。例如,"do(es)?" 可以匹配 "do" 、 "does" 中的 "does" 、 "doxy" 中的 "do" 。? 等价于 {0,1}。
    {n} 重复n次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。
    {n,} 重复n次或多次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。
    {n,m} 重复n次到m次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。

    贪婪匹配

    贪婪匹配:在满足匹配时,匹配尽可能长的字符串,默认情况下,采用贪婪匹配

    正则 待匹配字符 匹配结果 说明
    <.*> <abcdefg>2<hijklmn> <abcdefg>2<hijklmn> 默认为贪婪模式,会匹配尽量长的字符串
    <.*?> <abcdefg>2<hijklmn> <abcdefg> 加上? 为了将贪婪匹配模式转为非贪婪匹配模式,会匹配尽量短的字符串
    几个常用的非贪婪匹配Pattern
    *? 重复任意次,但尽可能少重复
    +? 重复1次或更多次,但尽可能少重复
    ?? 重复0次或1次,但尽可能少重复
    {n,m}? 重复n到m次,但尽可能少重复
    {n,}? 重复n次以上,但尽可能少重复 

    . *?的用法

    . 是任意字符
    * 是取 0 至 无限长度
    ? 是非贪婪模式。
    何在一起就是 取尽量少的任意字符,一般不会这么单独写,他大多用在:
    .*?x
    
    就是取前面任意长度的字符,直到一个x出现

    re模块

    在python中用来提供正则表达式匹配的模块就是re模块

    在re模块中的匹配语法有以下几种

    • re.match:从头开始匹配,匹配成功返回正则匹配成功的对象,匹配失败返回None
    • re.search:匹配包含的所有,匹配成功返回正则匹配成功的对象,匹配失败返回None
    • re.findall:将所有匹配到的字符以一个列表的形式返回,匹配失败返回一个空列表
    • re.finditer:和findall类似,将匹配到的所有字符作为一个迭代器返回
    • re.split:按照能够匹配的子串将字符串分割后返回列表
    • re.sub:匹配字符并替换
    • re.compile:编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。

    re.findall函数 *****

    • 格式:re.findall(pattern, string, flags=0)
    • 参数:
      pattern:匹配的正则表达式
      string:要匹配的字符串
      flags:标志位,用于控制正则表达式的匹配方式,可有可无
      标志位常见取值如下:
      re.I    忽略大小写
      re.L    作本地户识别
      re.M    多行匹配,影响^和$
      re.S    使.匹配包括换行符在内的所有字符
      re.U    根据Unicode字符集解析字符,影响w   W    B
      re.X    使我们以更灵活的格式理解正则表达式
    • 示例:
      ret = re.findall(r'd+', 'Today454 is1 a 00 day3')   # 匹配一位到多位的数字
      print(ret)
      # 结果>>> ['45', '1', '00', '3']
      ret = re.findall(r'[a-z]{3}', 'Today is a Good day, Day')   # 匹配任意连续三个小写字母
      print(ret)
      # 结果>>> ['oda', 'ood', 'day']
      ret = re.findall(r'[a-z]{3}', 'Today is a Good day, Day', flags=re.I)   # 匹配任意连续三个字母,不区分大小写;flags=re.I表示不区分大小写
      print(ret)
      # 结果>>> ['Tod', 'Goo', 'day', 'Day'] 
    • findall的优先级查询:
      import re
      
      ret = re.findall('www.(baidu|souhu).com', 'www.baidu.com')
      print(ret)
      # 结果>>> ['baidu']   这是因为findall会优先把匹配到的结果,组里的内容返回;如果想要匹配结果,取消权限即可
      
      ret = re.findall('www.(?:baidu|souhu).com', 'www.baidu.com')
      print(ret)
      # 结果>>> ['www.baidu.com']

    re.search函数 *****

    • 格式:re.search(pattern, string, flags=0)
    • 参数:
      pattern:匹配的正则表达式
      string:要匹配的字符串
      flags:标志位,用于控制正则表达式的匹配方式
    • 示例:
      ret = re.search(r'd', 'Today is a Good day, Day')
      print(ret)
      # 结果>>> <_sre.SRE_Match object; span=(2, 3), match='d'>
      print(ret.group())
      # 结果>>> d
      ret = re.search(r'j', 'Today is a Good day, Day')
      print(ret)
      # 结果>>> None

    re.match函数 ***

    • 格式:re.match(pattern, string, flags=0)
    • 参数:
      pattern:匹配的正则表达式
      string:要匹配的字符串
      flags:标志位,用于控制正则表达式的匹配方式
    • 示例:
      ret = re.match(r'www', 'www.baidu.com')
      print(ret)
      # 结果>>> <_sre.SRE_Match object; span=(0, 3), match='www'>
      print(ret.group())
      # 结果>>> www
      ret = re.match(r'www', 'ww.baidu.com')
      print(ret)
      # 结果>>> None

    re.sub函数 ***

    • 格式:re.sub(pattern, repl, string, count=0)
    • 参数:
      pattern:    正则表达式(规则)
      repl:       指定的用来替换的字符串
      string:     目标字符串
      count:      最多替换次数,如果不指定,默认全部替换
    • 示例:
      ret = re.sub(r'd', 'H', 'sjkd42jk234523jln5aex8439')
      print(ret)
      # 结果>>> sjkdHHjkHHHHHHjlnHaexHHHH
      ret = re.sub(r'd', 'H', 'sjkd42jk234523jln5aex8439',count=2)
      print(ret)
      # 结果>>> sjkdHHjk234523jln5aex8439
      
      # subn函数:其实和sub一样,只是返回替换了多少次
      ret = re.subn(r'd', 'H', 'sjkd42jk234523jln5aex8439')
      print(ret)
      # 结果>>> ('sjkdHHjkHHHHHHjlnHaexHHHH', 13)
      ret = re.subn(r'd', 'H', 'sjkd42jk234523jln5aex8439',count=2)
      print(ret)
      # 结果>>> ('sjkdHHjk234523jln5aex8439', 2)

    re.split函数 ***

    • 格式:re.split(pattern, string, maxsplit=0, flags=0)
    • 参数:
      pattern:匹配的正则表达式
      string:要匹配的字符串
      maxsplit : 指定分隔的次数;默认为0,不限制次数
      flags:标志位,用于控制正则表达式的匹配方式
    • 示例:
      ret = re.split(r'd+', 'www232abcdw3jafe32ad')
      print(ret)
      # 结果>>> ['www', 'abcdw', 'jafe', 'ad']
      ret = re.split(r'd+', 'www232abcdw3jafe32ad', maxsplit=2)
      print(ret)
      # 结果>>> ['www', 'abcdw', 'jafe32ad']
    • split的优先级查询
      ret = re.split('d+', 'sdjkfl3sdjl5jskd2dsf')
      print(ret)
      # 结果>>> ['sdjkfl', 'sdjl', 'jskd', 'dsf']
      ret = re.split('(d+)', 'sdjkfl3sdjl5jskd2dsf')
      print(ret)
      # 结果>>> ['sdjkfl', '3', 'sdjl', '5', 'jskd', '2', 'dsf']
      
      '''
      在匹配部分加上()之后所切出的结果是不同的,
      没有()的没有保留所匹配的项,但是有()的却能够保留了匹配的项,
      这个在某些需要保留匹配部分的使用过程是非常重要的。
      '''

    re.compile函数 *****

    • 格式:re.compile(pattern)
    • 参数:
      pattern:要编译的正则表达式
    • 示例:
      my_re = re.compile('d{3}')
      ret = re.findall(my_re, 'jdla2jd2462jskdf234546')
      print(ret)
      # 结果>>> ['246', '234', '546']
      ret = re.search(my_re, 'jdla2jd2462jskdf234546').group()
      print(ret)
      # 结果>>> 246
      ret = re.match(my_re, '43423sjdkfljaj24234').group()
      print(ret)
      # 结果>>> 434
      
      # 编译后的,都可以使用re模块的其他方法,如:findall、search、match、sub、split等

    re.finditer函数 *****

    • 格式:re.finditer(pattern, string, flags=0)
    • 参数:
      pattern:匹配的正则表达式
      string:要匹配的字符串
      flags:标志位,用于控制正则表达式的匹配方式
    • 示例:
      ret = re.finditer(r'd', 'sjkdfl3jskl9ajkl234jdkf75jdslf')
      for i in ret:
          print(i.group())
      # 结果>>>
      '''
      3
      9
      2
      3
      4
      7
      5
      '''

    分组 ***** 

    除了简单地判断是否匹配之外,正则表达式还有提取子串的强大功能。用()表示的就是要提取的分组

    str3 = "010-52365561"
    m = re.match(r"(d{3})-(d{8})", str3)
    c = re.match(r"(?P<first>d{3})-(d{8})", str3)     # ?P<>给组起名
    print(m)
    # 打印结果:<_sre.SRE_Match object; span=(0, 12), match='010-52365561'>
    print(m.group(0))   #使用序号获取对应组的信息,group(0)--代表原始的字符串
    # 打印结果:010-52365561
    print(m.group(1))
    # 打印结果:010
    print(m.group(2))
    # 打印结果:52365561
    print(m.groups())   #查看匹配的各组的情况
    # 打印结果:('010', '52365561')
    print(c.group("first"))
    # 打印结果:010

    扩展

    匹配标签

    ret = re.search(r'<(?P<tag_name>w+)>.+</(?P=tag_name)>', '<h1>Hello World</h1>')
    '''
    还可以在分组中利用?<name>的形式给分组起名字
    获取的匹配结果可以直接用group('名字')拿到对应的值
    '''
    print(ret.group())
    # 结果>>> <h1>Hello World</h1>
    print(ret.group('tag_name'))
    # 结果>>> h1
    
    ret = re.search(r'<(w+)>.+</(1)>', '<h1>Hello World</h1>')
    '''
    如果不给组起名字,也可以用序号来找到对应的组,表示要找的内容和前面的组内容一致
    获取的匹配结果可以直接用group(序号)拿到对应的值
    '''
    print(ret.group())
    # 结果>>> <h1>Hello World</h1>
    print(ret.group(1))
    # 结果>>> h1

    匹配整数

    ret = re.findall('d+', "1-2*(60+(-40.35/5)-(-4*3))")
    print(ret)
    # 结果>>> ['1', '2', '60', '40', '35', '5', '4', '3']
    ret = re.findall('-?d+.d+|(-?d+)', "1-2*(60+(-40.35/5)-(-4*3))")
    print(ret)  # 结果>>> ['1', '-2', '60', '', '5', '-4', '3']
    ret.remove('')
    print(ret)  # 结果>>> ['1', '-2', '60', '5', '-4', '3']

    数字匹配

    1、 匹配一段文本中的每行的邮箱
          http://blog.csdn.net/make164492212/article/details/51656638
    
    2、 匹配一段文本中的每行的时间字符串,比如:‘1990-07-12’;
    
       分别取出1年的12个月(^(0?[1-9]|1[0-2])$)、
       一个月的31天:^((0?[1-9])|((1|2)[0-9])|30|31)$
    
    3、 匹配qq号。(腾讯QQ号从10000开始)  [1,9][0,9]{4,}
    
    4、 匹配一个浮点数。       ^(-?d+)(.d+)?$   或者  -?d+.?d*
    
    5、 匹配汉字。             ^[u4e00-u9fa5]{0,}$ 

     

  • 相关阅读:
    数据库字段太多,批量快速建立实体类方法(适合大量字段建立实体类)
    SQL service 中的 ”输入SQL命令窗口“ 打开了 “属性界面” 回到 ”输入SQL命令窗口“
    计算机软件编程英语词汇集锦
    编程常用英语词汇
    svn上传和下载项目
    当启动tomcat时出现tomcat setting should be set in tomcat preference page
    Implicit super constructor Object() is undefined for default constructor. Must define an explicit constructor
    eclipse中选中一个单词 其他相同的也被选中 怎么设置
    Spring Boot的@SpringBootApplication无法引入的问题
    最全的SpringCloud视频教程
  • 原文地址:https://www.cnblogs.com/yanjieli/p/10049467.html
Copyright © 2011-2022 走看看