Python正则表达式之re模块

正则表达式概述
  • 前言
    在这里插入图片描述

  • 概念
    正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑(可以用来做检索,截取或者替换操作)

  • 简介
    正则表达式是对字符串(包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为“元字符”))操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。正则表达式是一种文本模式,模式描述在搜索文本时要匹配的一个或多个字符串

  • 作用

    1. 给定的字符串是否符合正则表达式的过滤逻辑(称作“匹配”)
    2. 可以通过正则表达式,从字符串中获取我们想要的特定部分。
    3. 还可以对目标字符串进行替换操作

在Python中需要通过正则表达式对字符串进行匹配的时候, 可以一个模
块, 名字为re

re模块之match的基本使用:
  • 语法:
 result = re.match(正则表达式,要匹配的字符串)
  • 意义:

    • re.match是用来进行正则匹配检查的方法,如果字符串开头的0个或多个字符匹配正则表达式模式,则返回相应的match对象。如果字符串不匹配模式,返回None(注意不是空字符串"")
    • 匹配对象Macth Object具有group()方法, 用来返回字符串的匹配部分,具有span()方法。返回匹配字符串的位置(元组存储开始,结束位置),具有start(),end()方法,存储匹配数据的开始和结束位置。(也可以通过对象的dir(对象查看对象的方法))
    • 注意:如果想在目标字符串的任意位置查找,需要使用re.search
  • 案例:(mathch vs search)

import re
pattern = 'Hello'
str1 = 'HelloWorld'
v = re.match(pattern,str1)
print(type(v)) # <class 're.Match'>
print(v)  # <re.Match object; span=(0, 5), match='Hello'>

print(dir(v))
# 使用group可以获取匹配到的数据
print(v.group()) # Hello
表示字符
  • 语法格式:
    字符功能
    .匹配任意一个字符(除了\n)
    []匹配列表中的字符
    \d匹配数字,即0-9
    \D匹配非数字
    \s匹配空白、即空格(\n,\t,\r,\f)
    \S匹配非空格
    \w匹配单词字符,即a-z, A-Z, 0-9, _
    \W匹配非单词字符
  • 使用示例1
import re
v = re.match('.','a')
v = re.match('.','1')
v = re.match('.','_')

#返回None
v = re.match('.','\n')
print(v)
v = re.match('\d','1')
print(v)
v = re.match('\D','a1')
print(v)
v = re.match('\s',' ')
v = re.match('\s','\n')
v = re.match('\s','\t')
print(v)
#非空格
v = re.match('\S',' ')
print(v)
v = re.match('\w','a')
v = re.match('\w','A')
v = re.match('\w','1')
v = re.match('\w','_')
print(v)

v = re.match('\W','a')
v = re.match('\W','A')
v = re.match('\W','1')
v = re.match('\W','_')
print(v)

v = re.match('\w\W','1a')
print(v)
  • 使用示例2:‘[]’的使用
#手机号匹配问题
v = re.match('\d\d\d\d\d\d\d\d\d\d\d','13312341234')
v=re.amtch("\d{11}",1563979865466131564897)
v = re.match('1[35789]\d\d\d\d\d\d\d\d\d','12312341234')
#\d == [0-9]
#\D == [^0-9]
#\w == [a-zA-Z0-9_]
#\W == [^a-zA-Z0-9_]
print(v)
表示数量(匹配多个字符)
  • 语法
    字符功能
    *匹配前一个字符出现0次或者无限次(可有可无)
    +匹配前一个字符出现1次或者无限次(至少有1次)
    匹配前一个字符串出现1次或者0次(要么1次要么没有)
    {m}匹配前一个字符出现m次
    {m,}匹配前一个字符至少出现m次
    {m,n}匹配前一个字符出现m到n次
  • 代码验证
import re
pattern = '\d*'
#注意,这时候表示数字可有可无,如果没有的话,则匹配''
v = re.match(pattern,'abc123')
print(v)
print('11111111111111')
pattern = '\d+'
v = re.match(pattern,'abc123')
print(v)
v = re.match(pattern,'123abc123')
print(v)
pattern = '\d?'
v = re.match(pattern,'123abc')
print(v)
pattern = '\d{3}'
v = re.match(pattern,'1234abc')
print(v)
pattern = '\d{3,}'
v = re.match(pattern,'1234abc')
print(v)

pattern = '\d{3,6}'
v = re.match(pattern,'1235674abc')
print(v)
  • 使用示例1 *

    • 匹配出一个字符串首字母为大写字符,后边都是小写字符,这些小写字母可有可无
      pattern = '[A-Z][a-z]*'
      v = re.match(pattern,'Hello')
      print(v)
      
  • 使用示例2 +

    • 匹配出有效的变量名
      #有效的变量名  开头为字母
      pattern = '[a-zA-Z_]+[\w_]*'
      v = re.match(pattern,'1name123')
      print(v)
      
      
  • 使用示例3 ?

    • 匹配出1-99之间的数字
      pattern = '[1-9][0-9]?'
      v = re.match(pattern,'09')
      print(v)
      v = re.match(pattern,'33')
      print(v)
      v = re.match(pattern,'7')
      print(v)
      
  • 使用示例4 {m}

    • 匹配出一个随机密码8-20位以内
      pattern = '[a-zA-Z0-9_]{8,20}'
      v = re.match(pattern,'dafadf22432adfag')
      print(v)
      
原始字符串
  • 概述:
    • Python中字符串前边加上 r 表示原生字符串
  • 示例:
    • 字符串中的使用
      • 字符串s = ‘\n123’ 与 s = r’\n123’
    • 正则中使用
      s = '\n123'
      print(s)
      s = r'\n123'
      print(s)
      # s = '\\n123'
      # print(s)
      # pattern = '\\\\n\d{3,}'
      pattern = r'\\n\d{3,}'
      v = re.match(pattern,s)
      print(v)
      
表示边界
  • 语法及意义:
    字符功能
    ^匹配字符串开头
    $匹配字符串结尾
    \b匹配一个单词的边界
    \B匹配非单词的边界
  • 案例:
    • 使用示例1 匹配QQ邮箱 &

      #匹配qq邮箱,  5-10位
      pattern = '[\d]{5,10}@qq.com'
      #必须限制结尾的
      # pattern = '[1-9]\d{4,9}@qq.com$'
      #正确的地址
      v = re.match(pattern,'12345@qq.com')
      #未限制结尾的前提下使用不正确的地址
      # v = re.match(pattern,'12345@qq.comabc')
      print(v)
      
    • 使用示例2 \b 匹配单词边界

      pattern = r'.*\bab'
      #ab左边界的情况
      v = re.match(pattern,'123 abr')
      print(v)
      
      pattern = r'.*ab\b'
      #ab为右边界的情况
      v = re.match(pattern,'wab')
      print(v)
      
    • 使用示例3 \B 匹配非单词边界

      #ab不为左边界
      pattern = r'.*\Bab'
      v = re.match(pattern,'123 abr')
      print(v)
      #ab不为右边界
      pattern = r'.*ab\B'
      v = re.match(pattern,'wab')
      print(v)
      
匹配分组
  • 语法
字符功能
-匹配左右任意一个表达式
(ab)将括号中的字符作为一个分组
\num引用分组num匹配到的字符串
?P<name>分别起组名
(?P=name)引用别名为name分组匹配到的字符串
  • 示例1 |的使用
    • 匹配0-100之间所有的数字

        pattern = '[0-9]+\d?$|100$'$|100$'
        v = re.match(pattern,'0')
        print(v)
        v = re.match(pattern,'10')
        print(v)
        v = re.match(pattern,'100')
        print(v)
        v = re.match(pattern,'99')
        print(v)
        v = re.match(pattern,'200')
        print(v)
        
      
  • 示例2 ()的使用
    • 匹配座机号码
      #匹配一个固定电话号码  010-66668888
      pattern = r'(\d+)-(\d{5,8}$)'
      v = re.match(pattern,'010-66668888')
      print(v) # <re.Match object; span=(0, 12), match='010-66668888'>
      print(v.group()) # 010-66668888
      
      print(v.group(1)) # 010
      print(v.group(2)) # 66668888
      print(v.groups()) # ('010', '66668888')
      print(v.groups()[0]) #  010
      print(v.groups()[1]) # 66668888
      
  • 示例3 \num 的使用
    • 匹配出网页标签内的数据
    s = '<html><title>我是标题</title></html>'
    #优化前
    # pattern = r'<.+><.+>.+</.+></.+>'
    # 优化后 可以使用分组  \2 表示引用第2个分组  \1表示引用第1个分组
    pattern = r'<(.+)><(.+)>.+</\2></\1>'
    v = re.match(pattern,s)
    print(v)
    #<re.Match object; span=(0, 32), match='<html><title>我是标题</title></html>'>
    print(v.group()) # <html><title>我是标题</title></html>
    print(v.groups()) # ('html', 'title')
    
  • 示例4 ?P<要起的别名> (?P=起好的别名)
    s = '<html><h1>我是一号字体</h1></html>'
    # pattern = r'<(.+)><(.+)>.+</\2></\1>'
    #如果分组比较多的话,数起来比较麻烦,可以使用起别名的方法?P<要起的名字>  以及使用别名(?P=之前起的别名)
    pattern = r'<(?P<key1>.+)><(?P<key2>.+)>.+</(?P=key2)></(?P=key1)>'
    v = re.match(pattern,s)
    print(v)
    
re模块的高级用法
  • search

    • 作用:
      • 扫描字符串,查找正则表达式模式产生匹配的第一个位置,并返回相应的匹配对象。如果字符串中没有与模式匹配的位置,则返回None;
    • 用法:
      import re
      v = re.match('\d+','阅读次数为 9999 次')
      print(v) # None
      v1 = re.search('\d+','阅读次数为 999 次')
      print(v1) # <re.Match object; span=(6, 9), match='999'>
      
  • findall

    • 作用

      • 从左到右扫描字符串,并按照找到的顺序返回匹配。如果模式中有一个或多个组,返回组列表
    • 用法

      list1 = re.findall(r'\d+',"阅读次数C:129 Python:999 C++:99")
      print(list1)
      # ['129', '999', '99']
      
  • sub

    • 作用:

      • 返回通过replace替换字符串。如果没有找到模式,则返回字符串不变
    • 用法1: 直接替换

      #将目标字符串中所有的字符'a'替换成'c'
      s = re.sub(r'a','c',"adfjalkdfkdasf")
      print(s) # cdfjclkdfkdcsf
      
    • 用法2: 使用函数(可以运算)替换

      def replace(result):
          print(type(result))
          print(type(result.group()))
          print(result.group())
          r = int(result.group())+ 1
          return str(r)
      #将目标字符串中所有的阅读次数+1
      v = re.sub(r'\d+',replace,"阅读次数C:129 Python:999 C++:99")
      print(v)
      
      <class 're.Match'>
      <class 'str'>
      129
      <class 're.Match'>
      <class 'str'>
      999
      <class 're.Match'>
      <class 'str'>
      99
      阅读次数C:130 Python:1000 C++:100
      
    
    
  • split

    • 作用:
      • 通过指定模式拆分字符串
    • 用法1:
      • 按指定的格式拆分字符串
      v = re.split(r',|-|:','Tom:HelloWorld,james-bond')
      print(v)
      # ['Tom', 'HelloWorld', 'james', 'bond']   
      
贪婪模式和非贪婪
  • 什么是贪婪模式?
    • Python里数量词默认是贪婪的, 总是尝试匹配尽可能多的字符
  • 什么是非贪婪
    • 与贪婪相反,总是尝试匹配尽可能少的字符,可以使用"*","?","+","{m,n}"后面加上,使贪婪变成非贪婪
  • 使用示例1:
    #贪婪模式,.+中的'.'会尽量多的匹配
    v = re.match(r'(.+)(\d+-\d+-\d+)','This is my tel:133-1234-1234')
    print(v.group())  # This is my tel:133-1234-1234
    print(v.group(1)) # This is my tel:13
    print(v.group(2)) # 3-1234-1234
    
    
    v = re.match(r'(.+?)(\d+-\d+-\d+)','This is my tel:133-1234-1234')
    print(v.group()) # This is my tel:133-1234-1234
    print(v.group(1)) # This is my tel:
    print(v.group(2)) # 133-1234-1234
    
  • 使用示例2
    #贪婪模式
    v= re.match(r'abc(\d+)','abc123')
    print(v.group(1)) # 123
    #非贪婪模式
    v= re.match(r'abc(\d+?)','abc123')
    print(v.group(1)) # 1
    
练习

import re
print(re.findall('\w','aAbc123_*()-='))
# ['a', 'A', 'b', 'c', '1', '2', '3', '_']
print(re.findall('\W','aAbc123_*()-= '))
#['*', '(', ')', '-', '=', ' ']
print(re.findall('\s','aA\rbc\t\n12\f3_*()-= '))
# ['\r', '\t', '\n', '\x0c', ' ']
print(re.findall('\S','aA\rbc\t\n12\f3_*()-= '))
#['a', 'A', 'b', 'c', '1', '2', '3', '_', '*', '(', ')', '-', '=']
print(re.findall('\d','aA\rbc\t\n12\f3_*()-= '))
# ['1', '2', '3']
print(re.findall('\D','aA\rbc\t\n12\f3_*()-= '))
# ['a', 'A', '\r', 'b', 'c', '\t', '\n', '\x0c', '_', '*', '(', ')', '-', '=', ' ']
print(re.findall('^what','what the wonderful tonight what'))
# ['what']
print(re.findall('烟雨$',"天青色 等 烟雨"))
# ['烟雨']
print(re.findall('sb$',""" 
                alex
                alex is
                alex
                sb"""))
# ['sb']
print(re.findall('^alex$','alex  is alex'))
print(re.findall('^alex$','al       ex'))
print(re.findall('^alex$','alex'))

# []
# []
# ['alex']

重复匹配:| . | * | ? | .* | .*? | + | {n,m} |

1、. 匹配除了\n之外任意一个字符,指定re.DOTALL之后才能匹配换行符

print(re.findall('a.b','a1b a2b a b abbbb a\nb a\tb a*b'))
# ['a1b', 'a2b', 'a b', 'abb', 'a\tb', 'a*b']
print(re.findall('a.b','a1b a2b a b abbbb a\nb a\tb a*b',re.DOTALL))
# ['a1b', 'a2b', 'a b', 'abb', 'a\nb', 'a\tb', 'a*b']

2、* 左侧字符重复0次或无穷次,性格贪婪

print(re.findall('ab*','a ab abb abbbbbbbb bbbbbbbb'))
# ['a', 'ab', 'abb', 'abbbbbbbb']

3、+左侧字符重复1次或无穷次,性格贪婪

print(re.findall('ab+','a ab abb abbbbbbbb bbbbbbbb'))
# ['ab', 'abb', 'abbbbbbbb']

4、左侧字符重复0次或1次,性格贪婪

print(re.findall('ab?','a ab abb abbbbbbbb bbbbbbbb'))
# ['a','ab','ab','ab']

5、{n,m}:左侧字符重复n次到m次,性格贪婪
下列表达式等价

 {0,} => *
 {1,} => +
 {0,1} => ?
 {n}表示单独一个n代表只出现n次,多一次不行少一次也不行
print(re.findall('ab{2,5}','a ab abb abbb abbbb abbbbbbbb bbbbbbbb'))
# ['abb', 'abbb', 'abbbb', 'abbbbb']

匹配小数

print(re.findall('\d+\.?\d*',"asdfasdf123as1111111.123dfa12adsf1asdf3"))
# ['123', '1111111.123', '12', '1', '3']

[] 匹配指定字符一个

print(re.findall('a\db','a1111111b a3b a4b a9b aXb a b a\nb'))
# ['a3b', 'a4b', 'a9b']
print(re.findall('a[0-5]b','a1111111b a3b a1b a0b a4b a9b aXb a b a\nb'))
# ['a3b', 'a1b', 'a0b', 'a4b']
print(re.findall('a[0-9a-zA-Z]b','a1111111b axb a3b a1b a0b a4b a9b aXb a b a\nb'))
# ['axb', 'a3b', 'a1b', 'a0b', 'a4b', 'a9b', 'aXb']
print(re.findall('a[-0-9\n]b','a-b a0b a1b a8b aXb a b a\nb'))
# ['a-b', 'a0b', 'a1b', 'a8b', 'a\nb']
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值