正则表达式和re模块

  1. 正则表达式

    • 什么是正则表达式

      • 一套匹配字符串的规则;

    • 能做什么

      • 检测输入字符串的合法性

      • 从一个大文件中找到符合规则的所有内容

  2. 字符组

    • 在同一个位置可能出现的各种字符组成了一个字符组,在正则表达式中用[]表示

    • [abc]可以匹配a、b、c

    • 字符组的的范围是根据ascii进行匹配的

      • [0-9] 数字

      • [a-zA-Z] 大小写

      • [0-9a-fA-F] 可以匹配数字,大小写形式的a~f,用来验证十六进制字符

    正则待匹配字符匹配结果说明
    [0123456789] 8 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-fA-F] e True 可以匹配数字,大小写形式的a~f,用来验证十六进制字符
  3. 元字符

    正则表达式中能够帮助我们表示匹配内容的符号

    元字符匹配内容
    . 匹配除换行符以外的任意字符
    \w 匹配字母或数字或下划线
    \s 匹配任意的空白符
    \d 匹配数字
    \n 匹配一个换行符
    \t 匹配一个制表符
    \b 匹配一个单词的结尾
    ^ 匹配字符串的开始
    $ 匹配字符串的结尾
    \W 匹配非字母或数字或下划线
    \D 匹配非数字
    \S 匹配非空白符
    a|b 匹配字符a或字符b
    () 匹配括号内的表达式,也表示一个组
    [...] 匹配字符组中的字符
    [^...] 匹配除了字符组中字符的所有字符

    [\d\D] 、 [\w\W] 、 [\s\S] 都可以表示匹配所有

  4. 量词

    量词用法说明
    * 重复零次或更多次
    + 重复一次或更多次
    ? 重复零次或一次
    {n} 重复n次
    {n,} 重复n次或更多次
    {n,m} 重复n到m次

    \d+(\.\d+) 整数或小数

  5. 贪婪匹配和非贪婪匹配

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

    正则待匹配字符匹配结果说明
    <.*> <script>...<script> <script>...<script> 默认为贪婪匹配模式,会匹配尽量长的字符串
    <.*?> <script>...<script> <script> <script> 加上?为将贪婪匹配模式转为非贪婪匹配模式,会匹配尽量短的字符串

    量词后面加上?,将贪婪匹配转化成非贪婪匹配

  6. 转义符

    • 原本有特殊意义的字符,到了表达它本身意义的时候需要转义

    • 有一些特殊意义的内容,放在字符组中会取消其特殊意义 [().*+?]

    • -在字符组中表示范围,取消该功能需要转义 [a\-z] 或者放在字符组最前面、最后面

    在正则表达式中,有很多有特殊意义的是元字符,比如\n和\s等,如果要在正则中匹配正常的"\n"而不是"换行符"就需要对""进行转义,变成'\'。

      在python中,无论是正则表达式,还是待匹配的内容,都是以字符串的形式出现的,在字符串中\也有特殊的含义,本身还需要转义。所以如果匹配一次"\n",字符串中要写成'\n',那么正则里就要写成"\\n",这样就太麻烦了。这个时候我们就用到了r'\n'这个概念,此时的正则是r'\n'就可以了。

    正则待匹配字符匹配 结果说明
    \n \n False 因为在正则表达式中\是有特殊意义的字符,所以要匹配\n本身,用表达式\n无法匹配
    \n \n True 转义\之后变成\\,即可匹配
    "\\n" '\n' True 如果在python中,字符串中的'\'也需要转义,所以每一个字符串'\'又需要转义一次
    r'\n' r'\n' True 在字符串之前加r,让整个字符串不转义
  7. re模块

    import  re
    #findall
    ret = re.findall('a', 'eva egon yuan')  # 返回所有满足匹配条件的结果,放在列表里
    print(ret) #结果 : ['a', 'a']
    #findall 优先级
    ret = re.findall('www.(baidu|wen).com', 'www.wen.com')
    print(ret)  # ['wen']     这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可
    ret = re.findall('www.(?:baidu|wen).com', 'www.wen.com')
    print(ret)  # ['www.wen.com']

    #search
    ret = re.search('a', 'eva egon yuan').group()
    print(ret) #结果 : 'a'
    # 函数会在字符串内查找模式匹配,只到找到第一个匹配然后返回一个包含匹配信息的对象,该对象可以
    # 通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。

    #split 分割
    ret=re.split('\d+','ase123we'r)
    print(ret)  #['ase','wer']
    ret=re.split('(\d+)','ase123wer')
    print(ret)  #['ase','123','wer']
    ret=re.split('\d(\d)\d','ase123wer')
    print(ret)  #['ase','2','wer']

    #sub subn替换
    ret=re.sub('\d+','H','aqz123qwe234',1) #可以指定替换的次数
    print(ret) #'aqzHqwe234'
    ret=re.subn('\d+','H','aqz123qwe234')
    print(ret) #(aqzHqweH,2) 返回元组包括替换后的字符串和替换的次数

    #match 匹配头,同search,不过尽在字符串开始处进行匹配
    ret = re.match('a', 'abc').group()  # 同search,不过尽在字符串开始处进行匹配
    print(ret)   #'a'

    #compile 将正则表达式编译成一个对象,多次使用时可以节省时间
    obj = re.compile('\d{3}')  #将正则表达式编译成为一个 正则表达式对象,规则要匹配的是3个数字
    ret = obj.search('abc123eeee') #正则表达式对象调用search,参数为待匹配的字符串
    ret1 = obj.findall('wee234tty345')
    print(ret.group())  #结果 : 123
    print(ret1)  #[234,345]

    #finditer 返回迭代器,节省空间
    ret = re.finditer('\d', 'ds3sy4784a')   #finditer返回一个存放匹配结果的迭代器
    print(ret)  # <callable_iterator object at 0x10195f940>
    print(next(ret).group())  #查看第一个结果
    print(next(ret).group())  #查看第二个结果
    print([i.group() for i in ret])  #查看剩余的结果
  1. 匹配标签 #(?P<名字>正则表达式)

    import re

    ret = re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>")
    #还可以在分组中利用?<name>的形式给分组起名字
    #获取的匹配结果可以直接用group('名字')拿到对应的值
    print(ret.group('tag_name'))  #结果 :h1
    print(ret.group())  #结果 :<h1>hello</h1>

    ret = re.search(r"<(\w+)>\w+</\1>","<h1>hello</h1>")
    #如果不给组起名字,也可以用\序号来找到对应的组,表示要找的内容和前面的组内容一致
    #获取的匹配结果可以直接用group(序号)拿到对应的值
    print(ret.group(1))
    print(ret.group())  #结果 :<h1>hello</h1>

    #分组命名的引用
    exp = '<abc>asrtyj58*(&*)</abc>dgyiad</qwe>'
    ret=re.search('<(?P<tag>\w+)>.*?</(?P=tag)>',exp)
    print(ret)  #'<abc>asrtyj58*(&*)</abc>'
  2.  

posted @ 2020-03-25 23:29  枫nian丶  阅读(83)  评论(0)    收藏  举报