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

    学习记录,小白一枚
  • 相关阅读:
    POJ 1251 Jungle Roads
    1111 Online Map (30 分)
    1122 Hamiltonian Cycle (25 分)
    POJ 2560 Freckles
    1087 All Roads Lead to Rome (30 分)
    1072 Gas Station (30 分)
    1018 Public Bike Management (30 分)
    1030 Travel Plan (30 分)
    22. bootstrap组件#巨幕和旋转图标
    3. Spring配置文件
  • 原文地址:https://www.cnblogs.com/wangsirde0428/p/14322631.html
Copyright © 2011-2022 走看看