栏目分类:
子分类:
返回
文库吧用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
文库吧 > IT > 软件开发 > 后端开发 > Python

python基础语法 - 正则表达式

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

python基础语法 - 正则表达式

正则表达式
  • 正则表达式字符串
    • 元字符
    • 转义字符
    • 开始与结束符
  • 字符类
    • 定义字符类
    • 字符类取反
    • 区间
    • 预定义字符类
  • 量词
    • 量词的使用
    • 贪婪和懒惰
  • 分组
    • 分组的使用
    • 分组命名
    • 反向引用分组
    • 非捕获分组
  • re模块
    • search()和match()函数
    • findall()和finditer()函数
    • 字符串分割
    • 字符串替换

  • 是什么:Regular Expression,简写RE,是预先定义好的一个“规则字符串”,通过这个规则字符串可以匹配、查找和替换那些符合规则的文本。
  • 优点:文本的查找替换虽然可以使用字符串提供的方法实现,但是实现较为困难,运算效率低。使用正则效率高。
  • 缺点:编写合适的正则表达式较为困难。
  • python中应用:数据挖掘、数据分析、网络爬虫、输入有效性验证等待。
正则表达式字符串
  • 正则表达式是一种字符串,它由普通字符和元字符组成的。
  • 普通字符:按照字符字面意义的字符。
  • 元字符:预先定义好的一些特定字符。
  • 如验证邮箱的正则表达式:w+@zhengzetang.com,其中w+、.属于元字符;@zhengzetang、com是普通字符。
元字符
  • 用来描述其他字符的特殊字符,由基本元字符和普通字符构成,基本元字符是构成元字符的组成要素。基本元字符有14个,如下表
转义字符
  • 以上面匹配邮箱的字符串w+@zhengzetang.com为例
  • w字符不表示英文字母w,而是表示任何语言的单词字符、数字或下划线等内容时,需要在w前面加上反斜杠“”。
  • .本身是基本元字符,代表任意一个字符,但是我们希望按照.字面的意义使用(就是一个点),这时候加上一个反斜杠“”就可以实现了。
  • 转义字符就是对普通字符或基本元字符,进行转义,用于其他功能。
开始与结束符
  • 前面提到了^和$,用以匹配一行字符串的开始和结束。
  • 当以^开始时,要求一行字符串的开始位置匹配。
  • 当以$结束时,要求一行字符串的结束位置匹配。
    import re 
    
    p1 = r'w+@tianshangrenjian.com'
    p2 = r'^w+@tianshangrenjian.com$'
    
    text = "My email is tong_guan588@tianshangrenjian.com."
    m = re.search(p1, text)
    print(m)
    
    # 匹配不到,有^,$符号,匹配时要求text字符串开始和结束都要与正则表达式开始和结束匹配。
    a = re.search(p2,text)
    print(a)
    
    # email字符串的开始与结束与正则表达式相匹配
    email = 'tong_guan588@tianshangrenjian.com'
    b = re.search(p2, email)
    print(b)
    
  • 显示结果
字符类
  • 正则表达式种可以使用字符类(character class),一个字符类定义一组字符,其中的任一字符出现在输入字符串中即匹配成功。
  • 注意:每次匹配只能匹配字符串中的一个字符。
定义字符类
  • 定义一个普通的字符类,使用[]元字符类。例,想在字符串中匹配java或Java,可以使用正则表达式[Jj]ava
    import re
    
    p = r'[Jj]ava'
    
    # 可以匹配
    m = re.search(p, 'i like Java and Python')
    print(m)
    
    # 可以匹配
    c = re.search(p, 'i like java and Python')
    print(c)
    
    # 不可匹配
    b = re.search(p, 'i like JAVA and Python')
    print(b)
    
    # 想要匹配JAVA,可以使用|
    p2 = r'java|JAVA|Java'
    d = re.search(p2, 'i like JAVA and Python')
    print(d)
    
  • 运行结果为
字符类取反
  • 在正则表达式中指定不想出现的字符, 可以在字符前加^符号。
    import re 
    
    p = r'[^0123456789]'
    
    # 不匹配数字
    m = re.search(p, '239120392')
    print(m)
    
    # 除了非数字外,都可以匹配任意字符
    a = re.search(p, 'Reasdskf')
    print(a)
    
  • 运行结果
区间
  • 如果要表示连续的数字,用[^0123456789],较为复杂,可以使用区间符号-表示。即[^0123456789]等同于[^0-9]
  • 连续的英文字母可以表示为[a-z],大写[A-Z]。
  • 可以表示多个不同区间,如[A-Za-z0-9]表示所有字母和数字字符类,[0-25-7]表示0,1,2,5,6,7
    import re 
    
    p = r'[a-zA-Z0-9]'
    
    # 匹配
    m = re.search(p, 'A10.3')
    print(m)
    
    # 不匹配
    a = re.search(r'[0-25-7]', 'A3489C')
    print(a)
    
预定义字符类
  • 有些字符很常用,如[0-9]等,为了书写方便,正则表达式提供了预定义的字符类。
  • 示例
    import re
    
    # p = r'[^0123456789]'
    p = r'D'
    
    # 不匹配
    m = re.search(p, '11003')
    print(m)
    
    # 匹配
    a = re.search(p, 'ajdka')
    print(a)
    
    text = "hello world。"
    b = re.search(p, text)
    print(b)
    
  • 运行结果
量词
  • 上面说的正则,只能匹配显示一次字符或字符串,如果想匹配显示多次字符或字符串可以使用量词。
量词的使用
  • 量词表示字符或字符串重复的次数,量词如下表
字符说明
?出现零次或一次
*出现零次或多次
+出现一次或多次
{n}出现n次
{n, m}至少出现n次但不超过m次
{n, }至少出现n次
  • 示例
    import re
    
    m = re.search(r'd?', '87654321')   # 出现数字一次,匹配字符8
    print(m)
    
    a = re.search(r'd?', 'adxcx')      # 出现数字0次,匹配''
    print(a)
    
    b = re.search(r'd*', '2134354afas123') # 出现数字多次,匹配2134354
    print(b)
    
    c = re.search(r'd{8}', '87654321')     # 出现数字8次,匹配87654321
    print(c)
    
    d = re.search(r'd{9,}', '87654321')    # 出现数字8次,但要求9次,不匹配
    print(d)
    
  • 运行结果
贪婪和懒惰
  • 量词细分为贪婪量词和懒惰量词。
  • 贪婪量词会尽可能多地匹配字符,懒惰量词会尽可能少地匹配字符。
  • 大多数计算机语言的正则表达式词默认是贪婪的,要想使用懒惰量词在量词后面加 ?
    import re
    
    # 使用贪婪量词
    m = re.search(r'd{5,8}', '87456123')   # 至少出现5次,不少于8次,贪婪匹配8次
    print(m)
    
    # 使用懒惰量词
    a = re.search(r'd{5,8}?', '87456123')  # 懒惰匹配5次
    print(a)
    
  • 运行结果
分组
  • 分组也称为子表达式,就是将一个字符串放到一对小括号中,让一个字符串作为整体使用量词。
分组的使用
  • 对正则分组不仅可以对一个字符串整体使用量词,也可以在正则中引用已存在的分组。

  • 示例

    import re
    
    p = r'(121){2}'
    m = re.search(p, '121121121adfd')   # 匹配121121
    print(m)
    print(m.group())    # 返回匹配的字符串
    print(m.group(1))   # 返回第一组内容
    
    a = r'(d{3,4})-(d{7,8})'
    b = re.search(a, '010-7785457322a')
    print(b)
    print(b.group())
    print(b.group(1))
    
  • 运行结果

分组命名
  • 组命名:在组开头添加?P<分组名>
  • 分组命名后,方便程序访问分组。
  • 示例
    import re
    
    p = r'(?Pd{3,4})-(?Pd{7,8})'
    
    b = re.search(p, '010-77548573')
    print(b)
    print(b.group())
    print(b.groups())
    
    # 通过组编号返回
    print(b.group(1))
    print(b.group(2))
    
    # 通过组名返回
    print(b.group('area_code'))
    print(b.group('phone_code'))
    
  • 运行结果
反向引用分组
  • 要说清这个意思,我们先举个例子,如果要解析XML代码
    import re
    
    p = r'<([w]+)>.*'
    m = re.search(p, 'abc')
    print(m)
    
    a = re.search(p, 'erd')
    print(a)
    
  • 运行结果,a不是我们想要的,但是也能匹配出来,怎么办呢?
  • 分析正则表达式
  • 如上图,正则的两个分组内容一样,但是匹配出来的与不一样,因此上述正则不能实现我们想要的结果。如果把第二个分组改成反向引用第一组,即可实现,组编号都是从1开始的,反向引用语法为:组编号。
    import re
    
    p = r'<([w]+)>.*'
    m = re.search(p, 'abc')
    print(m)
    
    a = re.search(p, 'erd')
    print(a)
    
  • 运行结果为
非捕获分组
  • 捕获分组:匹配子表达式的结果被暂时保存到内存中,以备表达式或其他程序使用,这个过程就是“捕获”,捕获结果可以通过组编号或组名进行引用。
  • 非捕获分组:与上面相反,不想存,不想引用,只是单纯的匹配。
  • 实现方法:组开头使用?:
    import re
    
    s = 'img1.png, img2.png, img3.jpg, img4.png'
    
    # 捕获分组,将括号中的内容作为子表达式进行捕获匹配,将组的内容返回
    p1 = r'w+(.png)'
    mlist = re.findall(p1,s)
    print(mlist)
    
    # 非捕获分组,将括号中的内容作为普通正则字符串进行整体匹配,即找到.png结尾的文本
    p2 = r'w+(?:.png)'
    nlist = re.findall(p2,s)
    print(nlist)
    
  • 运行结果
re模块
  • re模块是python内置的正则表达式模块。
search()和match()函数
  • 两者非常相似, 区别如下:
    • search():在输入字符串中查找,返回第一个匹配内容,找到就匹配对象,没找到就返回None。
    • match():在输入字符串开始处查找匹配内容,找到就匹配对象,没找到就返回None。
  • 示例
    import re
    
    p = r'w+@woaipython.com'
    
    text = 'my email is coucher42@woaipython.com'
    # 能匹配
    m = re.search(p,text)
    print(m)
    
    # 不能匹配
    n = re.match(p,text)
    print(n)
    
    email = 'coucher42@woaipython.com'
    # 能匹配
    a = re.search(p,email)
    print(a)
    
    # 能匹配
    b = re.match(p, email)
    print(b) 
    
  • 运行结果
  • match对象的几个方法:
    email = 'coucher42@woaipython.com'
    b = re.match(p, email)
    print(b)
    print(b.group())
    print(b.start())
    print(b.span())
    print(b.end())
    
  • 运行结果
findall()和finditer()函数
  • 两者相似,区别如下:
    • findall():在输入字符串中查找所有匹配内容,如果匹配成功,返回match列表对象,否则返回None。
    • finditer():在输入字符串中查找所有匹配内容,如果匹配成功,返回容纳match的可迭代对象,通过迭代对象每次可以返回一个match对象,如果失败则返回None。
    import re
    
    p = r'[Pp]ython'
    text = 'i like python or Python.'
    
    match_list = re.findall(p, text)
    print(match_list)
    
    match_iter = re.finditer(p, text)
    for i in match_iter:
        print(i)
        print(i.group())
    
  • 运行结果
字符串分割
  • 函数split(),按照匹配的子字符串进行分割,返回字符串列表对象。
  • 构造方式:re.split(pattern, string, maxsplit=0, flags=0)
  • pattern:正则表达式
  • string:要分割的字符串
  • maxsplit:最大分割次数,默认为0,意味着分割次数没有限制
  • flags:编译标志。
    import re
    p = r'd+'
    text = 'ABCD12EF33gh'
    
    clist = re.split(p, text)
    print(clist)
    
    dlist = re.split(p, text, maxsplit=1)
    print(dlist)
    
    elist = re.split(p, text, maxsplit=2)
    print(elist)
    
  • 运行结果
字符串替换
  • 函数sub(),用于替换匹配的字符串,返回值是替换之后的字符串。
  • 构造方式:re.sub(pattern, repl, string, count=0, flags=0)
  • pattern:正则表达式
  • repl:要替换字符串
  • string:要提供的字符串
  • count:要替换的最大数量,默认为0,意味着替换没有次数
  • flags:编译标志
    import re 
    p = r'd+'
    text = 'ABCD12EF33gh'
    
    replace_text = re.sub(p, ' ', text)
    print(replace_text)
    replace_text = re.sub(p, ' ', text, count=1)
    print(replace_text)
    replace_text = re.sub(p, ' ', text, count=2)
    print(replace_text)
    
  • 运行结果
转载请注明:文章转载自 www.wk8.com.cn
本文地址:https://www.wk8.com.cn/it/1038811.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 wk8.com.cn

ICP备案号:晋ICP备2021003244-6号