★ 正则表达式基本概念

正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个 "规则字符串",这个"规则字符串"用来表达对字符串的一种过滤逻辑.

★ 字符匹配

  • 单字符匹配

    字符 功能
    . 匹配任意1个字符(除了\n)
    [ ] 匹配[ ]中列举的字符
    \d 匹配数字,即0-9
    \D 匹配非数字,即不是数字
    \s 匹配空白,即 空格,tab键
    \S 匹配非空白
    \w 匹配单词字符,即a-z、A-Z、0-9、_
    \W 匹配非单词字符
  • 多字符匹配

    字符 功能
    * 匹配前一个字符出现0次或者无限次,即可有可无
    + 匹配前一个字符出现1次或者无限次,即至少有1次
    ? 匹配前一个字符出现1次或者0次,即要么有1次,要么没有
    匹配前一个字符出现m次
    匹配前一个字符出现从m到n次
  • 匹配开头结尾

    字符 功能
    ^ 匹配字符串开头
    $ 匹配字符串结尾
  • 匹配分组

    字符 功能
    | 匹配左右任意一个表达式
    (ab) 将括号中字符作为一个分组
    \num 引用分组num匹配到的字符串
    (?P) 分组起别名
    (?P=name) 引用别名为name分组匹配到的字符串
  • 基本使用

    • 案例1
      import re
      
      ret = re.match("([^-]*)-(\d+)","010-12345678")
      print(ret.group())
      print(ret.group(1))
      print(ret.group(2))
      
      # 运行结果:
      '010-12345678'
      '010'
      '12345678'
      
    • 案例2
      import re
      
      labels = ["<html><h1>www.itcast.cn</h1></html>", "<html><h1>www.itcast.cn</h2></html>"]
      
      for label in labels:
          ret = re.match(r"<(\w*)><(\w*)>.*</\2></\1>", label)
          if ret:
              print("%s 是符合要求的标签" % ret.group())
          else:
              print("%s 不符合要求" % label)
          
      # 运行结果:
      <html><h1>www.itcast.cn</h1></html> 是符合要求的标签
      <html><h1>www.itcast.cn</h2></html> 不符合要求
      
    • 案例3
      import re
      
      ret = re.match(r"<(?P<name1>\w*)><(?P<name2>\w*)>.*</(?P=name2)></(?P=name1)>", "<html><h1>www.itcast.cn</h1></html>")
      print(ret.group())
      
      # 运行结果:
      '<html><h1>www.itcast.cn</h1></html>'
      

re 高级用法

  • 语法规则

    • match(pattern,string): 匹配字符串的开头
      pattern: 正则表达式
      string: 要进行匹配的字符串
      返回一个匹配对象
    • search(pattern, string): 匹配字符串的任意位置
      pattern: 正则表达式
      string: 要进行匹配的字符串
      返回一个匹配对象
    • findall(pattern, string): 匹配所有符合条件的内容
      pattern: 正则表达式
      string:要进行匹配的字符串
      返回所有符合条件的内容的列表
    • sub(pattern, repl, string, count=0): 替换匹配到的内容
      pattern: 正则表达式
      repl:要替换成的内容
      string:要进行替换的字符串
      count:要替换的次数,默认为0,表示无限次
      返回替换后的字符串
    • split(pattern, string[,maxsplit]): 将匹配到的内容作为分割字符进行字符串的分割
      pattern:正则表达式
      string:要进行分割的字符串
      maxsplit:最大分割次数
      返回分割后的字符串列表
  • 案例演示

    • search 使用
      #coding=utf-8
      import re
      
      ret = re.search(r"\d+", "阅读次数为 9999")
      ret.group()
      
      运行结果:
      '9999'
      
    • findall 使用
      #coding=utf-8
      import re
      
      ret = re.findall(r"\d+", "python = 9999, c = 7890, c++ = 12345")
      print(ret)
      
      运行结果:
      ['9999', '7890', '12345']
      
    • sub 使用
      #coding=utf-8
      eg1:
      import re
      
      ret = re.sub(r"\d+", '998', "python = 997")
      print(ret)
      
      运行结果:
      python = 998
      
      
      eg2:
      #coding=utf-8
      import re
      
      def add(temp):
          strNum = temp.group()
          num = int(strNum) + 1
          return str(num)
      
      ret = re.sub(r"\d+", add, "python = 997")
      print(ret)
      
      ret = re.sub(r"\d+", add, "python = 99")
      print(ret)
      
      运行结果:
      python = 998
      python = 100
      
  • 贪婪与非贪婪

    • 基本概念

      Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;
      非贪婪则相反,总是尝试匹配尽可能少的字符。在"*","?","+","{m,n}"后面加上?,使贪婪变成非贪婪。
      
    • 案例演示

      >>> re.match(r"aa(\d+)","aa2343ddd").group(1)
      '2343'
      >>> re.match(r"aa(\d+?)","aa2343ddd").group(1)
      '2'
      >>> re.match(r"aa(\d+)ddd","aa2343ddd").group(1) 
      '2343'
      >>> re.match(r"aa(\d+?)ddd","aa2343ddd").group(1)
      '2343'
      
  • r的作用

    • 使用演示

      >>> mm = "c:\\a\\b\\c"
      >>> mm
      'c:\\a\\b\\c'
      >>> print(mm)
      c:\a\b\c
      >>> re.match("c:\\\\",mm).group()
      'c:\\'
      >>> ret = re.match("c:\\\\",mm).group()
      >>> print(ret)
      c:\
      >>> ret = re.match("c:\\\\a",mm).group()
      >>> print(ret)
      c:\a
      >>> ret = re.match(r"c:\\a",mm).group()
      >>> print(ret)
      c:\a
      >>> ret = re.match(r"c:\a",mm).group()
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
      AttributeError: 'NoneType' object has no attribute 'group'
      >>>
      
    • 使用总结

      Python中字符串前面加上 r 表示原生字符串, 与大多数编程语言相同,正则表达式里使用"\"作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"\",那么使用编程语言表示的正则表达式里将需要4个反斜杠"\\":前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。
      Python里的原生字符串很好地解决了这个问题,有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。