美文网首页
09.正则表达式re-1.正则表达式

09.正则表达式re-1.正则表达式

作者: JerryChenn07 | 来源:发表于2018-09-24 17:24 被阅读11次

    1、正则表达式概述

    正则表达式(英语:Regular Expression,在代码中常简写为regex、regexp或RE),是计算机科学的一个概念。
    正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。
    在很多文本编辑器里,正则表达式通常被用来检索、替换那些匹配某个模式的文本。

    2、re模块

    2.1re 模块

    使 Python语言拥有全部的正则表达式功能。
    re 模块提供了一些函数,这些函数使用一个模式字符串做为它们的第一个参数,用于正则表达式匹配和替换。

    2.2re模块的使用

    • re.match 函数

    re.match 尝试从字符串的起始位置匹配一个模式,若字符串起始位置匹配正则表达式,则match方法返回匹配对象(Match Object),如果不是起始位置匹配成功的话,match()就返回none(注意不是“空字符串”)。

    • 语法:

    re.match(pattern, string, flags=0)

    • 参数:
    pattern – 匹配的正则表达式 
    
    string – 要匹配的字符串。 
    
    flags – 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
    
    匹配对象Macth Object具有group方法,我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。
    
    group(num=0) 
    匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。 
    
    groups() 
    返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。
    
    示例1:
    
    # 导入re模块
    import re
    
    # 使用match方法进行匹配操作
    result = re.match(正则表达式,要匹配的字符串)
    
    # 如果上一步匹配到数据的话,可以使用group方法来提取数据
    result.group()
    
    示例2:
    
    import re
    
    ret = re.match("taobao","taobao.com")
    print(ret)
    print(ret.group())
    
    运行结果:
    
    <_sre.SRE_Match object; span=(0, 6), match='taobao'>
    taobao
    

    3、表示字符

    正则表达式的单字符匹配:

    字体 功能
    . 匹配任意一个字符(除了\n)
    [] 匹配[]中列举的字符
    \d 匹配数字,即0-9
    \D 匹配非数字,即不是数字
    \s 匹配空白,即 空格,tab键
    \S 匹配非空白
    \w ==匹配包括下划线的任何单词字符。类似但不等价于“[A-Za-z0-9_]”,这里的"单词"字符使用Unicode字符集。==
    \W 匹配非单词字符

    匹配中文字符的正则表达式: [\u4e00-\u9fa5]

    • 示例1:‘.’

    匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。

    ret = re.match('.','a')
    print(ret.group())
    
    ret = re.match('.','A')
    print(ret.group())
    
    ret = re.match('.',' ')
    print(ret.group())
    
    ret = re.match('.','\nab')
    print(ret.group())     错误
    
    ret = re.match('..','\rab')
    print(ret.group())
    
    ret = re.match('..','\tab')
    print(ret.group())
    
    ret = re.match('.','好好学习')
    print(ret.group())
    
    ret = re.match('....','好好学习')
    print(ret.group())
    
    • 示例2:’[ ]‘

    用来表示一组字符,单独列出:[amk] 匹配 ‘a’,’m’或’k’

    ret = re.match('[Hh]','hello')
    print(ret.group())
    
    ret = re.match('[Hh]','Hello')
    print(ret.group())
    
    ret = re.match('[A-Z]','Hello')
    print(ret.group())
    
    ret = re.match('[0-9a-z]','00')
    print(ret.group())
    
    ret = re.match('[0-9a-z]','aa')
    print(ret.group())
    
    ret = re.match('[\u4e00-\u9fa5]*','陈佳睿')
    print(ret)
    print(ret.group())
    
    • 示例3:’\d, \D, \s, \S‘

    \d – 匹配一个数字字符。等价于 [0-9]。

    \D –匹配一个非数字字符。等价于 [^0-9]。

    \s –匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。

    \S –匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。

    ret = re.match('小米\d','小米6')
    print(ret.group())
    
    ret = re.match('小\D\d','小米6')
    print(ret.group())
    
    ret = re.match('\s',' 小米')
    print(ret)
    
    ret = re.match('\s','\nab')
    print(ret)
    
    ret = re.match('\S','小米')
    print(ret)
    
    ret = re.match('\S','0123')
    print(ret)
    
    ret = re.match('\S\S\S','x米6')
    print(ret)
    
    
    运行结果:
    小米6
    小米6
    <_sre.SRE_Match object; span=(0, 1), match=' '>
    <_sre.SRE_Match object; span=(0, 1), match='\n'>
    <_sre.SRE_Match object; span=(0, 1), match='小'>
    <_sre.SRE_Match object; span=(0, 1), match='0'>
    <_sre.SRE_Match object; span=(0, 3), match='x米6'>
    
    • 示例4:’\w, \W‘

    \w ==匹配包括下划线的任何单词字符。类似但不等价于“[A-Za-z0-9_]”,这里的"单词"字符使用Unicode字符集。==。

    \W 匹配任何非单词字符。等价于 ‘[^A-Za-z0-9_]’。

    ret = re.match('\w','hello')
    print(ret)
    
    ret = re.match('\w\w','_hello')
    print(ret)
    
    ret = re.match('\w','陈')
    print(ret)
    
    ret = re.match('\W\W\w','。.Hello')
    print(ret)
    
    ret = re.match('\W','陈hello')
    print(ret)  #None
    
    ret = re.match('\W','陈hello',re.ASCII) #匹配各个国家文字
    print(ret)  #<_sre.SRE_Match object; span=(0, 1), match='陈'>\
    
    ret = re.match('[\u4e00-\u9fa5]','哈hello')
    print(ret)
    
    运行结果:
    <_sre.SRE_Match object; span=(0, 1), match='h'>
    <_sre.SRE_Match object; span=(0, 2), match='_h'>
    <_sre.SRE_Match object; span=(0, 1), match='陈'>
    <_sre.SRE_Match object; span=(0, 3), match='。.H'>
    None
    <_sre.SRE_Match object; span=(0, 1), match='陈'>
    <_sre.SRE_Match object; span=(0, 1), match='哈'>
    

    4、原始字符串

    >>> mm = "c:\\a\\b\\c"
    >>> mm
    'c:\\a\\b\\c'
    >>> print(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里的原生字符串很好地解决了这个问题,有了原始字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。

    >>> ret = re.match(r"c:\\a",mm).group()
    >>> print(ret)
    c:\a
    

    5、表示数量

    匹配多个字符的相关格式

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

    6、表示边界

    字符 功能
    ^ 匹配字符串开头
    $ 匹配字符串结尾
    \b 匹配一个单词的边界
    \B 匹配非单词边界
    • 示例1:$

    需求:匹配163.com的邮箱地址

    import re
    
    # 正确的地址
    ret = re.match("[\w]{4,20}@163\.com", "xiaoWang@163.com")
    ret.group()
    
    # 不正确的地址
    ret = re.match("[\w]{4,20}@163\.com", "xiaoWang@163.comheihei")
    ret.group()
    
    # 通过$来确定末尾
    ret = re.match("[\w]{4,20}@163\.com$", "xiaoWang@163.comheihei")
    ret.group()
    
    • 示例2: \b
    >>> re.match(r".*\bver\b", "ho ver abc").group()
    'ho ver'
    
    >>> re.match(r".*\bver\b", "ho verabc").group()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'NoneType' object has no attribute 'group'
    
    >>> re.match(r".*\bver\b", "hover abc").group()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'NoneType' object has no attribute 'group'
    
    • 示例3:\B
    >>> re.match(r".*\Bver\B", "hoverabc").group()
    'hover'
    
    >>> re.match(r".*\Bver\B", "ho verabc").group()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'NoneType' object has no attribute 'group'
    
    >>> re.match(r".*\Bver\B", "hover abc").group()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'NoneType' object has no attribute 'group'
    
    >>> re.match(r".*\Bver\B", "ho ver abc").group()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'NoneType' object has no attribute 'group'
    

    7、匹配分组

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

    需求:匹配出0-100之间的数字

    import re
    
    ret = re.match("[1-9]?\d","8")
    print(ret)
    
    ret = re.match("[1-9]?\d","78")
    print(ret)
    
    # 不能正常匹配到的情况
    ret = re.match("[1-9]?\d","08")
    print(ret)
    
    # 修正之后的
    ret = re.match("[1-9]?\d$","8")
    print(ret)
    
    # 添加|
    ret = re.match("[1-9]?\d$|100","8")
    print(ret)
    
    ret = re.match("[1-9]?\d$|100","78")
    print(ret)
    
    ret = re.match("[1-9]?\d$|100","8")
    print(ret)
    
    ret = re.match("[1-9]?\d$|100","100")
    print(ret)
    
    运行结果:
    <_sre.SRE_Match object; span=(0, 1), match='8'>
    <_sre.SRE_Match object; span=(0, 2), match='78'>
    <_sre.SRE_Match object; span=(0, 1), match='0'>
    <_sre.SRE_Match object; span=(0, 1), match='8'>
    <_sre.SRE_Match object; span=(0, 1), match='8'>
    <_sre.SRE_Match object; span=(0, 2), match='78'>
    <_sre.SRE_Match object; span=(0, 1), match='8'>
    <_sre.SRE_Match object; span=(0, 3), match='100'>
    
    • 示例2:( )

    需求:匹配出163、126、qq邮箱之间的数字

    import re
    
    ret = re.match("\w{4,20}@163\.com", "test@163.com")
    ret.group()
    
    ret = re.match("\w{4,20}@(163|126|qq)\.com", "test@126.com")
    ret.group()
    
    ret = re.match("\w{4,20}@(163|126|qq)\.com", "test@qq.com")
    ret.group()
    
    ret = re.match("\w{4,20}@(163|126|qq)\.com", "test@gmail.com")
    ret.group()
    
    >>> ret = re.match("([^-]*)-(\d+)","010-12345678")
    >>> ret.group()
    '010-12345678'
    >>> ret.group(1)
    '010'
    >>> ret.group(2)
    '12345678'
    
    • 示例3:\

    需求:匹配出<html>hh</html>

    import re
    
    # 能够完成对正确的字符串的匹配
    ret = re.match("<[a-zA-Z]*>\w*</[a-zA-Z]*>", "<html>hh</html>")
    ret.group()
    
    # 如果遇到非正常的html格式字符串,匹配出错
    ret = re.match("<[a-zA-Z]*>\w*</[a-zA-Z]*>", "<html>hh</htmlbalabala>")
    ret.group()
    
    # 正确的理解思路:如果在第一对<>中是什么,按理说在后面的那对<>中就应该是什么
    
    # 通过引用分组中匹配到的数据即可,但是要注意是元字符串,即类似 r""这种格式
    ret = re.match(r"<([a-zA-Z]*)>\w*</\1>", "<html>hh</html>")
    ret.group()
    
    # 因为2对<>中的数据不一致,所以没有匹配出来
    ret = re.match(r"<([a-zA-Z]*)>\w*</\1>", "<html>hh</htmlbalabala>")
    ret.group()
    
    • 示例4:\number

    需求:匹配出<html><h1>www.taobao.com</h1></html>

    import re
    
    ret = re.match(r"<(\w*)><(\w*)>.*</\2></\1>", "<html><h1>www.taobao.com</h1></html>")
    ret.group()
    
    ret = re.match(r"<(\w*)><(\w*)>.*</\2></\1>", "<html><h1>www.taobao.com</h2></html>")
    ret.group()
    
    • 示例5:(?P<name>) (?P=name)

    需求:匹配出<html><h1>www.taobao.com</h1></html>

    import re
    
    ret = re.match(r"<(?P<name1>\w*)><(?P<name2>\w*)>.*</(?P=name2)></(?P=name1)>", "<html><h1>www.taobao.com</h1></html>")
    ret.group()
    
    ret = re.match(r"<(?P<name1>\w*)><(?P<name2>\w*)>.*</(?P=name2)></(?P=name1)>", "<html><h1>www.taobao.com</h2></html>")
    ret.group()
    

    (?P<name>)和(?P=name)中的字母P大写

    8、re模块的高级用法

    8.1search

    需求:匹配出文章阅读的次数
    import re
    
    ret = re.search(r"\d+", "阅读次数为 9999")
    print(ret.group())
    
    9999
    

    8.2findall

    需求:统计出python、c、c++相应文章阅读的次数
    import re
    
    ret = re.findall(r"\d+", "python = 9999, c = 7890, c++ = 12345")
    print(ret)
    
    ['9999', '7890', '12345']
    

    8.3sub 将匹配到的数据进行替换

    需求:将匹配到的阅读次数加1
    方法1:
    import re
    
    ret = re.sub(r"\d+", '998', "python = 997")
    print(ret)
    
    python = 998
    
    
    
    
    
    方法2:
    import re
    
    def add(temp):
        strNum = temp.group()
        num = int(strNum) + 1
        return str(num)
    
    ret = re.sub(r"\d+", add, "python = 997 java=100")
    print(ret)
    
    ret = re.sub(r"\d+", add, "python = 99")
    print(ret)
    
    
    python = 998 java=101
    python = 100
    
    从下面的字符串中取出文本
    <div>
            <p>岗位职责:</p>
    <p>完成推荐算法、数据统计、接口、后台等服务器端相关工作</p>
    <p><br></p>
    <p>必备要求:</p>
    
    
    re.sub(r'</?\w*>|\n|\s','',s)
    

    8.4split

    • 根据匹配进行切割字符串,并返回一个列表
    需求:切割字符串“info:xiaoZhang 33 shandong”
    
    
    import re
    
    ret = re.split(r':| ','info:xiaoZhang 33 shandong')
    print(ret)
    
    
    ['info', 'xiaoZhang', '33', 'shandong']
    

    9、贪婪和非贪婪

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

    s="This is a number 234-235-22-423"
    
    ret = re.match(".+(\d+-\d+-\d+-\d+)",s)
    print(ret.group())
    
    This is a number 234-235-22-423
    
    ret = re.match(".+?(\d+-\d+-\d+-\d+?)",s)
    print(ret.group())
    
    This is a number 234-235-22-4
    

    正则表达式模式中使用到通配字,那它在从左到右的顺序求值时,会尽量“抓取”满足匹配最长字符串,在我们上面的例子里面,“.+”会从字符串的启始处抓取满足模式的最长字符,其中包括我们想得到的第一个整型字段的中的大部分,“\d+”只需一位字符就可以匹配,所以它匹配了数字“4”,而“.+”则匹配了从字符串起始到这个第一位数字4之前的所有字符。
    解决方式:非贪婪操作符“?”,这个操作符可以用在"*","+","?"的后面,要求正则匹配的越少越好。

    相关文章

      网友评论

          本文标题:09.正则表达式re-1.正则表达式

          本文链接:https://www.haomeiwen.com/subject/erhhoftx.html