zoukankan      html  css  js  c++  java
  • 035.Python正则表达式


    正则表达式 

    一 介绍

    拼正则表达式是什么?

    • 它是约束字符串匹配某种形式的规则

    正则表达式有什么用?

    1. 检测某个字符串是否符合规则比如:判断手机号,身份证号是否合法
    2. 提取网页字符串中想要的数据.比如:爬虫中,提取网站天气,信息,股票代码,星座运势等具体关键字

    线测试工具http://tool.chinaz.com/regex

    正则表达式由一些[普通字符]和一些[元字符]组成:

    (1)普通字符包括大小写字母和数字

    (2)元字符具有特殊含义,大体种类分为如下

    1. 预定义字符集,字符组
    2. 量词
    3. 边界符
    4. 分组

    二 正则表达式findall

    2.1 单字符匹配

    findall("正则表达式","要匹配的字符串")

    d 和 D

    • d 匹配数字
    • D 匹配非数字
    import re
    lst = re.findall("d","davfdardwer24523`de3r43wqe#$@!dwd@#!2143DC")
    print (lst)
    lst = re.findall("D","davfdardwer24523`de3r43wqe#$@!dwd@#!2143DC")
    print (lst)

    执行

    [root@node10 python]# python3 test.py
    ['2', '4', '5', '2', '3', '3', '4', '3', '2', '1', '4', '3']
    ['d', 'a', 'v', 'f', 'd', 'a', 'r', 'd', 'w', 'e', 'r', '`', 'd', 'e', 'r', 'w', 'q', 'e', '#', '$', '@', '!', 'd', 'w', 'd', '@', '#', '!', 'D', 'C']

    w和W

    • w 匹配字母数字下换线 (正则函数中,支持中文匹配)
    • W 匹配非字母,数字,下划线
    import re
    lst = re.findall("w","dwer_=|:';.你好世界24523`de3re#$@!dwd@#!2143DC")
    print (lst)
    lst = re.findall("W","dwer_=|:';.你好世界24523`de3re#$@!dwd@#!2143DC")
    print (lst)

    执行

    'd', 'w', 'e', 'r', '_', '你', '好', '世', '界', '2', '4', '5', '2', '3', 'd', 'e', '3', 'r', 'e', 'd', 'w', 'd', '2', '1', '4', '3', 'D', 'C']
    ['=', '\', '|', ':', "'", ';', '.', '`', '#', '$', '@', '!', '@', '#', '!']

    s和S

    • s 匹配任意的空白符( )
    • S 匹配任意的非空白符
    复制代码
    import re
    strvar = '                                      '
    lst = re.findall("s",strvar)
    print(lst)
    strvar = "  8989sdf     111"
    lst = re.findall("S",strvar)
    print(lst)
    复制代码

    执行

    [root@node10 python]# python3 test.py
    [' ', '	', '	', '	', '	', '	']
    ['8', '9', '8', '9', 's', 'd', 'f', '1', '1', '1']

    • 匹配一个换行
    • 匹配一个缩进
    复制代码
    import re
    strvar = """
    sdfsd   sdfsdf   sfsdfsdf
    sdfsddffg       dfgdfg  fgdfg
    """
    lst = re.findall("
    ",strvar)
    print(lst)
    lst = re.findall("	",strvar)
    print(lst)
    复制代码

    字符组 [123]

    [123] 必须从字符组当中挑出一个出来,个数上有要求,必须一个,如果匹配不到就是空.

    import re
    lst = re.findall("[123]","sdfs3fkj5kj")
    print(lst)
    
    print(re.findall('a[abc]b','aab abb acb adb'))

    执行

    [root@node10 python]# python3 test.py
    ['3']
    ['aab', 'abb', 'acb']

    字符组

    复制代码
    import re
    # [0123456789] => [0-9] -是一个特殊字符,代表范围0-9 0到9
    print(re.findall('a[0123456789]b','a1b a2b a3b acb ayb'))
    print(re.findall("a[0-9]b",'a1b a2b a3b acb ayb'))
    
    #[abcdefg] => [a-g] 表达所有小写字符可以用[a-z]
    print(re.findall('a[a-z]b','a1b a2b a3b acb ayb adb')) #['acb', 'ayb', 'adb']
    # print(re.findall('a[abcdefg]b','a1b a2b a3b acb ayb adb')) #['acb', 'adb']
    
    # [ABCDEFG] A-G  [A-Z]用来表达所有大写字符
    print(re.findall('a[A-Z]b','a1b a2b a3b  aAb aDb aYb')) #['aAb', 'aDb', 'aYb']
    print(re.findall('a[ABCDEFG]b','a1b a2b a3b  aAb aDb aYb')) #aAb aDb
    
    
    print(re.findall('a[0-9a-zA-Z]b','a-b aab aAb aWb aqba1b'))  #['aab', 'aAb', 'aWb', 'aqb', 'a1b']
    print(re.findall('a[0-9][*#/]b','a1/b a2b a29b a56b a456b')) #['a1/b']
    # 字符组当中的^ 代表除了的意思
    # 除了+ - * / 这些字符之外,剩下的都能匹配
    print(re.findall('a[^-+*/]b',"a%b ccaa*bda&bd")) #['a%b', 'a&b']
    # 在特殊字符前面加商一个\,让原本有意义的字符变得无意义,用于正则字符匹配
    print(re.findall('a[^]b',"a^b")) #['a%b', 'a&b']
    复制代码

    执行

    复制代码
    [root@node10 python]# python3 test.py
    ['a1b', 'a2b', 'a3b']
    ['a1b', 'a2b', 'a3b']
    ['acb', 'ayb', 'adb']
    ['aAb', 'aDb', 'aYb']
    ['aAb', 'aDb']
    ['aab', 'aAb', 'aWb', 'aqb', 'a1b']
    ['a1/b']
    ['a%b', 'a&b']
    ['a^b']
    复制代码

    2.2 正则匹配多个字符

    量词

    复制代码
    import re
    '''1) ? 匹配0个或者1个a '''
    print(re.findall('a?b','abbzab abb aab'))
    '''2) + 匹配1个或者多个a '''
    print(re.findall('a+b','b ab aaaaaab abb'))
    '''3) * 匹配0个或者多个a '''
    print(re.findall('a*b','b ab aaaaaab abbbbbbb'))
    '''4) {m,n} 匹配m个至n个a '''
    print(re.findall('a{1,3}b','aaab ab aab abbb aaz aabb'))
    复制代码

    执行

    [root@node10 python]# python3 test.py
    ['ab', 'b', 'ab', 'ab', 'b', 'ab']
    ['ab', 'aaaaaab', 'ab']
    ['b', 'ab', 'aaaaaab', 'ab', 'b', 'b', 'b', 'b', 'b', 'b']
    ['aaab', 'ab', 'aab', 'ab', 'aab']

    2.3 贪婪匹配 和 非贪婪匹配

    贪婪匹配:

    • 默认向更高次数匹配,程序当中默认使用贪婪匹配

    非贪婪匹配:

    • 默认向更少次数匹配
    • 语法:只需要在量词的后面再加上一个?号

    底层用的时回溯算法:
    从左到右开始寻找,直到找到最后再也找不到了,回头,找离右侧最近的那个值返回

    复制代码
    import re
    strvar = "刘能和刘罗锅和刘备有3儿子4"
    #.表示除了
    以外的任意字符
    lst = re.findall("刘.",strvar) print (lst) #.?表示刘后的字符可以出现1次或者多个
    lst = re.findall("刘.?",strvar) print(lst) #.+表示刘后的的任意字符出现0个或者多个
    lst = re.findall("刘.+",strvar) print(lst)
    lst = re.findall("刘.*",strvar) print(lst)
    lst = re.findall("刘.*子",strvar) print(lst)
    lst = re.findall("刘.{1,20}",strvar) print(lst) lst = re.findall("刘.{1,20}子",strvar) print(lst) print("非贪婪匹配") lst = re.findall("刘.??",strvar) print(lst) lst = re.findall("刘.+?",strvar) print(lst) lst = re.findall("刘.*?",strvar) print(lst) lst = re.findall("刘.*?子",strvar) print(lst) lst = re.findall("刘.{1,20}?",strvar) print(lst) # 默认使用的是贪婪模式,一直找到最后一个子,如果使用非贪婪,找到第一个字就立刻返回. lst = re.findall("刘.{1,20}?子",strvar) print(lst)
    复制代码

    执行

    复制代码
    ['刘能', '刘罗', '刘备']
    ['刘能', '刘罗', '刘备']
    ['刘能和刘罗锅和刘备有3儿子4子']
    ['刘能和刘罗锅和刘备有3儿子4子']
    ['刘能和刘罗锅和刘备有3儿子4子']
    ['刘能和刘罗锅和刘备有3儿子4子']
    ['刘能和刘罗锅和刘备有3儿子4子']
    非贪婪匹配 ['刘', '刘', '刘'] ['刘能', '刘罗', '刘备'] ['刘', '刘', '刘'] ['刘能和刘罗锅和刘备有3儿子'] ['刘能', '刘罗', '刘备'] ['刘能和刘罗锅和刘备有3儿子']
    复制代码

    2.4 边界符 ^ $

    例: w 以w作为左边界  d 以d作为右边界

     它默认是一个转义字符 退格 backspace
    需要通过字符串前面加上r,让转义字符失效,呈现正则的含义.

    复制代码
    import re
    #只匹配右边界d lst = re.findall(r"d","word pwd abc") print(lst)
    #匹配右边界前的任意字符 lst = re.findall(r".*d","word pwd abc") print(lst) # 能够匹配到一个右边界d ,就立刻返回 # .可以匹配空白符,除了 ,剩下所有字符都能匹配到 lst = re.findall(r".*?d","word pwd abc") print(lst)
    #匹配到非空白符 lst = re.findall(r"S*?d","word pwd abc") # 纯单词,舍去空格 print(lst)
    #匹配以w开头的非空白符 lst = re.findall(r"wS*","word pwd abc") #'word' print(lst)
    复制代码

    执行

    复制代码
    [root@node10 python]# python3 test.py
    ['d', 'd']
    ['word pwd']
    ['word', ' pwd']
    ['word', 'pwd']
    ['word']
    复制代码

    2.5 使用^$

    • 如果使用了^ 或者 $
    • ^ : 必须以某个字符开头,后面剩下的无所谓
    • $ : 必须以某个字符结尾,前面剩下的无所谓
    • 意味着把这个字符串当成一个整体
    复制代码
    import re
    strvar = "大哥大嫂大爷"
    print ("匹配大后面出\n的任意字符")
    print(re.findall('大.',strvar))
    print ("匹配以大开头后面出
    的任意字符,同时把这个字符串看成一个整体")
    print(re.findall('^大.',strvar)) # 只匹配一个,把字符串开成整体
    print ("必须以一个任意字符结尾")
    print(re.findall('大.$',strvar)) # 只匹配一个,把字符串开成整体
    # strvar = "大书"
    print ("以大开头,以任意字符结尾的两个字符,为空")
    print(re.findall('^大.$',strvar))
    print ("以大开头,匹配.*,?只是非贪婪匹配")
    print(re.findall('^大.*?$',strvar))
    print ("以g开头,匹配到空格停止")
    print(re.findall('^g.*? ' , 'giveme 1gfive gay'))
    print ("以e结尾,向前找到five,打出 ")
    print(re.findall('five$' , 'aassfive'))
    print ("以c结尾,匹配abc打印")
    print(re.findall("abc$","abcabcabc"))
    print ("全部卡死")
    print(re.findall('^giveme$' , 'giveme'))
    print ("完全卡死,并不匹配,返回空")
    print(re.findall('^giveme$' , 'giveme giveme'))
    print ("以g开头,e结尾,中间匹配任意")
    print(re.findall('^g.*?e$' , 'giveme giveme'))
    print ("匹配giveme,有两个")
    print(re.findall('giveme' , 'giveme giveme'))
    print ("以g开头,卡到e")
    print(re.findall("^g.*e",'giveme 1gfive gay'))
    print ("以g开头,卡到e,并使用非贪婪匹配")
    print(re.findall("^g.*?e",'giveme 1gfive gay'))
    复制代码

    执行

    复制代码
    [root@node10 python]# python3 test.py
    匹配大后面出
    的任意字符
    ['大哥', '大嫂', '大爷']
    匹配以大开头后面出
    的任意字符,同时把这个字符串看成一个整体
    ['大哥']
    必须以一个任意字符结尾
    ['大爷']
    以大开头,以任意字符结尾的两个字符,为空
    []
    以大开头,匹配.*,?只是非贪婪匹配
    ['大哥大嫂大爷']
    以g开头,匹配到空格停止
    ['giveme ']
    以e结尾,向前找到five,打出
    ['five']
    以c结尾,匹配abc打印
    ['abc']
    全部卡死
    ['giveme']
    完全卡死,并不匹配,返回空
    []
    以g开头,e结尾,中间匹配任意
    ['giveme giveme']
    匹配giveme,有两个
    ['giveme', 'giveme']
    以g开头,卡到e
    ['giveme 1gfive']
    以g开头,卡到e,并使用非贪婪匹配
    ['give']
    复制代码

    2.6 正则表达式分组匹配

    正常分组

    1. 正常情况下用()圆括号进行分组 可以用1 反向引用第一个圆括号匹配的内容。
    2. (?:正则表达式) 表示取消优先显示的功能
    复制代码
    import re
    print("匹配所有_good前的任意字符打印出")
    print(re.findall('.*?_good','wusir_good alex_good xboyww_good'))
    print("匹配所有的姓名")
    print(re.findall('(.*?)_good','wusir_good alex_good xboyww_good'))
    print("匹配所有的姓名,然后取消分组")
    print(re.findall('(?:.*?)_good','wusir_good alex_good secret男_good'))
    复制代码

    执行

    复制代码
    [root@node10 python]# python3 test.py
    匹配所有_good前的任意字符打印出
    ['wusir_good', ' alex_good', ' xboyww_good']
    匹配所有的姓名
    ['wusir', ' alex', ' xboyww']
    匹配所有的姓名,然后取消分组
    ['wusir_good', ' alex_good', ' secret男_good']
    复制代码

    a|b 匹配字符a 或者 匹配字符b  把字符串长的写在前面,字符串短的写在后面

    • | 代表或的意思
    import re
    res = re.findall("abcd|abc","abcdabcdabcd abc")
    print(res)

    执行

    [root@node10 python]# python3 test.py
    ['abcd', 'abcd', 'abcd', 'abc']

    2.7 匹配小数

    import re
    strvar = " 3.14 .34 35. ... 2.41.3 34.."
    res  = re.findall("d+.d+",strvar)
    print(res)

    执行 

    [root@node10 python]# python3 test.py
    ['3.14', '2.41']

    匹配小数和整数

    import re
    
    strvar = "3.15 34 .. 3434.23.234.2323 .34.34 .3434 .. .. nihao"
    res = re.findall("d+.d+|d+",strvar)
    print(res)

    执行

    [root@node10 python]# python3 test.py
    ['3.15', '34', '3434.23', '234.2323', '34.34', '3434']

    优化版

    findall 这个函数默认优先显示小括号里面的内容,如果不想显示,用?:
    小括号代表的是分组,放到一起代表整体,这个例子要么出现小数点和后面的值,要么不出现.

    import re
    
    strvar = "3.15 34 .. 3434.23.234.2323 .34.34 .3434 .. .. nihao"
    res = re.findall("d+(?:.d+)?",strvar)
    print(res)

    执行

    [root@node10 python]# python3 test.py
    ['3.15', '34', '3434.23', '234.2323', '34.34', '3434']

    匹配135或171的手机号 

    import re
    res = re.findall("(?:135|171)d{8}","13588889897 17180668088")
    print(res)

    执行

    [root@node10 python]# python3 test.py
    ['13588889897', '17180668088']

    正则要求卡主开头和结尾,且长度是11位 (这个例子开头结尾满足,但长度不对)

    import re
    res = re.findall("(?:^135|^171)d{8}$","13588889897 17180668088")
    print(res)

    执行

    [root@node10 python]# python3 test.py
    []

    #(?:     ^135      |      ^171     )

    import re
    res = re.findall("(?:^135|^171)d{8}$","17188889897")
    print(res)

    执行

    [root@node10 python]# python3 test.py
    ['17188889897']

    三 search 正则方法 

    3.1 介绍

    search("正则表达式","要匹配的字符串")
    它返回的是一个对象

    • 对象.属性
    • 对象.方法()
    • 想要获取对象里面的值用group()方法
    • 想要获取分组里面的值用groups()方法

    和 findall区别

    1. findall 找出所有匹配的结果,从左到右,返回的是列表
    2. search 找出一个结果就返回,从左到右,返回的是对象
    import re
    obj = re.search("d+","ksj323rf33sdf*&*&  78787878")
    print(obj)
    res = obj.group()
    print(res)

    执行

    [root@node10 python]# python3 test.py
    <_sre.SRE_Match object; span=(3, 6), match='323'>
    323

    3.2 基本使用

    匹配www.baidu.com 或者 www.google.com

    复制代码
    import re
    obj = re.search("(www).(baidu|google).(com)","www.baidu.com www.google.com")
    res = obj.group()
    #通过group拿到实际匹配的内容 print(res) #通过groups拿到小括号里面匹配的内容
    res = obj.groups() print(res)
    复制代码

    执行

    [root@node10 python]# python3 test.py
    www.baidu.com
    ('www', 'baidu', 'com')

    同一时间,既可以拿到匹配的结果,又可以拿到小括号里的内容,而findall不具备

    findall 同一时间只能拿取一种结果,要么是实际匹配的,要么是小括号的.

    search 只能匹配一个, findall 可以匹配所有. 这是两个函数之间的差别.

    复制代码
    import re
    obj = re.search("(www).(baidu|google).(com)","www.baidu.com www.google.com")
    res = obj.group()
    print(res) #www.baidu.com
    res = obj.groups()
    print(res)
    res = re.findall("(www).(baidu|google).(com)","www.baidu.com www.google.com")
    print(res)
    复制代码

    执行

    [root@node10 python]# python3 test.py
    www.baidu.com
    ('www', 'baidu', 'com')
    [('www', 'baidu', 'com'), ('www', 'google', 'com')]

    3.3 对比两个函数区别

    匹配出5*4 或者 6/8

    复制代码
    import re
    strvar = "5*4+6/8"
    obj = re.search("d+[*/]d+",strvar)
    # 获取对象当中的值
    res = obj.group()
    print(res)
    
    res= re.findall("d+[*/]d+",strvar)
    print(res)
    复制代码

    执行

    [root@node10 python]# python3 test.py
    5*4
    ['5*4', '6/8']

    一般有分组的情况下用search 更多,找到所有匹配条件一般用findall

    学习记录,小白一枚
  • 相关阅读:
    Intellij IDEA 一些不为人知的技巧
    IDEA配置GIT
    返回数据
    IDEA字体设置
    @RequestParam
    @RequestMapping
    基于jquery fly插件实现加入购物车抛物线动画效果,jquery.fly.js
    js倒计时代码 适合于促销-倒计时代码
    phpstorm 10 注册码
    dispaly:table-cell,inline-block,阐述以及案例
  • 原文地址:https://www.cnblogs.com/wangsirde0428/p/14322631.html
Copyright © 2011-2022 走看看