zoukankan      html  css  js  c++  java
  • 正则的用法

    正则表达式: 匹配内容,findall()方法将匹配到的内容返回列表,需引入re模块
    1.1 匹配单个字符:
    import re  # 首先引入re模块
    # 匹配单个字符的用法:
    # (1) d:匹配数字
    lst = re.findall("d","字符 1q2we34re6fdsf8dg")
    print(lst) # ['1', '2', '3', '4', '6', '8'] 将后面的字符串按照元素拆开,是数字的就放到列表里面
    # (2) D: 匹配非数字
    lst = re.findall("D","23fjs字符")
    print(lst) # ['f', 'j', 's', '字', '符']
    
    # (3) w: 匹配数字字母下滑线和中文
    lst = re.findall("w","27 j3 _d_晴朗")
    print(lst) # ['2', '7', 'j', '3', '_', 'd', '_', '晴', '朗']
    # (4) W: 匹配非数字字母下划线中文
    lst = re.findall("W"," 3fs字符 %#")
    print(lst) # [' ', ' ', '%', '#']
    
    # (5) s: 匹配任意空格符 
    ,
    ,	
    lst = re.findall("s"," 38s sjf 	  ")
    print(lst) # [' ', ' ', ' ', '	', ' ', ' ']
    # (6) S: 匹配非空格符
    lst = re.findall("S","34sdf 9 	 ")
    print(lst) # ['3', '4', 's', 'd', 'f', '9']
    
    # (7) 
    : 匹配换行符
    str1 = """
    换行显示
    
    """
    lst = re.findall("
    ",str1)
    print(lst) # ['
    ', '
    ', '
    ']

    1.2 字符组:  匹配中括号里列举的内容

    lst = re.findall("[abc]","oputuopctyauobpt")
    print(lst) # ['c', 'a', 'b']
    
    print(re.findall('a[abc]b','aab abb acb adb')) # ['aab', 'abb', 'acb']  # 匹配的数据必须以a开头,以b结尾,
    
    print(re.findall('a[0123456789]b','a1b a2b a3b acb ayb')) # ['a1b', 'a2b', 'a3b']
    # 优化: -是一个特殊的字符,代表的是一个范围 0-9 0123456789
    print(re.findall('a[0-9]b','a1b a2b a3b acb ayb')) # ['a1b', 'a2b', 'a3b']
    
    print(re.findall('a[abcdefg]b','a1b a2b a3b acb ayb adb')) # ['acb', 'adb']
    # 优化: [a-g]  如果想要表达所有的26个小写字母[a-z]
    print(re.findall('a[a-g]b','a1b a2b a3b acb ayb adb')) # ['acb', 'adb']
    
    print(re.findall('a[ABCDEFG]b','a1b a2b a3b  aAb aDb aYb')) # ['aAb', 'aDb']
    # 优化: [A-G]  如果想要表达所有的26个大写字母[A-Z]
    print(re.findall('a[A-G]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']
    # 注意: [0-z] 数字 小写 大写 还有特殊字符 比如@ ...
    print(re.findall('a[0-z]b','a@b aab aAb aWb aqba1b')) # ['a@b', 'aab', 'aAb', 'aWb', 'aqb', 'a1b']
    
    print(re.findall('a[0-9][*#/]b','a1/b a2b a29b a56b a456b')) # ['a1/b']

    1.3 量词: 多个字符的匹配 ?,+,*

    # ?: 代表匹配?前面字符的0次或者1次
    print(re.findall('a?b','abbzab abb aab')) # ['ab', 'b', 'ab', 'ab', 'b', 'ab']
    
    # +: 代表匹配+前面字符的1次或者多次,就是至少一次
    print(re.findall('a+b','b ab aaaaaab abb')) # ['ab', 'aaaaaab', 'ab']
    
    # *:代表匹配*前面字符的0次或者多次,就是任意次
    print(re.findall('a*b','b ab aaaaaab abbbbbbb')) # ['b', 'ab', 'aaaaaab', 'ab', 'b', 'b', 'b', 'b', 'b', 'b']
    
    # {m,n}: 匹配m到n次,包含m和n
    #  1 <= a <= 3
    print(re.findall('a{1,3}b','aaab ab aab abbb aaz aabb')) # ['aaab', 'ab', 'aab', 'ab', 'aab']
    # 前面修饰的a , 必须是2个字符
    print(re.findall('a{2}b','aaab ab aab abbb aaz aabb')) # ['aab', 'aab', 'aab']
    # 前面修饰的a , 至少是2个字符
    print(re.findall('a{2,}b','aaab ab aab abbb aaz aabb')) # ['aaab', 'aab', 'aab']

    1.4 贪婪模式与非贪婪模式: 一般默认是贪婪模式, 用?在量词后面修饰变成非贪婪模式

                                            贪婪模式: 默认向更多次匹配,底层用回溯算法,走到最后再回头,返回最后一个符合条件的匹配值, 效率比非贪婪模式高

                  非贪婪模式:默认匹配更少的次数,用一个?修饰在量词的后面

    strvar = "刘能和刘老根和刘铁棍子777子888"
    # 贪婪匹配
    lst = re.findall("刘.",strvar)
    print(lst) # ['刘能', '刘老', '刘铁']
    
    lst = re.findall("刘.?",strvar)
    print(lst) # ['刘能', '刘老', '刘铁']
    
    lst = re.findall("刘.+",strvar)
    print(lst) # ['刘能和刘老根和刘铁棍子777子888']
    
    lst = re.findall("刘.*",strvar)
    print(lst) # ['刘能和刘老根和刘铁棍子777子888']
    
    lst = re.findall("刘.{1,21}",strvar)
    print(lst) # ['刘能和刘老根和刘铁棍子777子888']
    
    lst = re.findall("刘.*子",strvar)
    print(lst) # ['刘能和刘老根和刘铁棍子777子']
    
    # 非贪婪匹配
    lst = re.findall("刘.??",strvar)
    print(lst) # ['刘', '刘', '刘']
    
    lst = re.findall("刘.+?",strvar)
    print(lst) # ['刘能', '刘老', '刘铁']
    
    lst = re.findall("刘.*?",strvar)
    print(lst) # ['刘', '刘', '刘']
    
    lst = re.findall("刘.{1,21}?",strvar)
    print(lst) # ['刘能', '刘老', '刘铁']
    
    lst = re.findall("刘.*?子",strvar)
    print(lst) # ['刘能和刘老根和刘铁棍子']
    
    lst = re.findall("天??","天空很蓝天气很好")
    print(lst) # ['', '', '', '', '', '', '', '', '']  # 代表0次或者1次的非贪婪匹配,所以匹配为空

    1.5 特殊字符:  ^, -, \, ., , ^, $

    # ^ 在字符组当中, 代表除了中括号里的元素,需放到字符组的左边第一个位置
    print(re.findall('a[^-+*/]b',"a%b ccaa*bda&bd")) # ['a%b', 'a&b']  除开-+*/这些字符,匹配其余符合条件的
    
    # 如果想要匹配^ 或者 -, 在原来的字符前面加上\,让字符的含义失效.
    lst = re.findall(r"e[^-]f","e^f e-f")
    print(lst) # ['e^f', 'e-f']
    
    # 匹配 \,在斜杠前再加一个斜杠,防止斜杠转义,代表一个斜杠
    lst = re.findall(r"a\c","ac")
    print(lst) # ['a\c'] 两个斜杠实际代表一个
    print(lst[0]) # ac
    
    # .表示匹配任意字符,除了换行符
    
    lst = re.findall(".","w3sf
    ")
    print(lst) # ['w', '3', 's', 'f']
    lst = re.findall(".","33s . s
    ")
    print(lst) # ['3', '3', 's', ' ', '.', ' ', 's']
    
    # 边界符  ^ $
    # 表示卡住字符的开头和结尾,是一个转义字符
    strvar = "word pwd scf"
    lst = re.findall(r".*d",strvar) # 表示元素必须以d结尾
    print(lst) # ['word pwd']
    
    lst = re.findall(r".*?d",strvar)
    print(lst) # ['word', ' pwd']
    
    lst = re.findall(r"w",strvar)
    print(lst) # ['w']  只匹配w且以w开头
    
    lst = re.findall(r"w.*?",strvar)
    print(lst) # ['w']
    
    # # 正则表达式中写字符时,要谨慎,下面例子必须匹配到第一个空格时,才结束
    lst = re.findall(r"w.*? ",strvar)
    print(lst) # ['word ']
    
    lst = re.findall(r"wS*",strvar)
    print(lst) # ['word']
    
     # ^ $: ^表示必须以..开头,$表示必须以..结尾.如果字符串中出现^和$,则要把这个字符串当做一个整体来匹配
    strvar = "天空天气天气"
    print(re.findall('天.',strvar))  # ['天空', '天气', '天气']
    print(re.findall('^天.',strvar)) # ['天空']
    print(re.findall('天.$',strvar)) # ['天气']
    print(re.findall('^天.$',strvar)) # [] 将字符串当做整体来看,没有以.结尾的
    print(re.findall('^天.*?$',strvar)) # ['天空天气天气'] 将字符串当做整体来看
    print(re.findall('^天.*?天$',strvar)) # []
    print(re.findall('^天.*?气$',strvar)) # ['天空天气天气']
    
    print(re.findall('^g.*? ' , 'giveme 1gfive gay')) # ['giveme ']
    print(re.findall('five$' , 'aassfive')) # ['five']
    print(re.findall('^giveme$' , 'giveme')) # ['giveme']
    print(re.findall('^giveme$' , 'giveme giveme')) # []
    print(re.findall('giveme' , 'giveme giveme')) # ['giveme', 'giveme']
    print(re.findall("^g.*e",'giveme 1gfive gay')) # ['giveme 1gfive']

    1.6 匹配分组:  用(),有分组的功能,可以优先显示,用?:表示取消括号里的优先分组

    # 要所有的姓名
    str1 = 'wusir_good alex_good secret男_good'
    print(re.findall("(.*?)_good",str1)) # ['wusir', ' alex', ' secret男']  括号里优先显示
    # ?: 不显示括号里面的内容
    print(re.findall('(?:.*?)_good','wusir_good alex_good secret男_good'))
     # ['wusir_good', ' alex_good', ' secret男_good']
    
    # |表示或,匹配到|前面或者后面的字符都符合条件,通常都将较难(较长)的条件放|前面,将较易(较短)的条件放|后面
    strvar = "abcddd"
    lst = re.findall("a|b",strvar)
    print(lst) # ['a', 'b']
    
    strvar = "abc24234234ddabcd234234"
    lst = re.findall("abc|abcd",strvar)
    print(lst)   # ['abc', 'abc']  优先匹配abc,在匹配abcd,所以只匹配到abc
    lst = re.findall("abcd|abc",strvar)
    print(lst)   # ['abc', 'abcd']  优先匹配abcd,在匹配abc
    
    # (1)匹配小数
    strvar = "5.33 3.13 34 34.  .98 9.99 sdfsdf  ......"
    lst = re.findall(r"d+.d+",strvar)
    print(lst) # ['5.33', '3.13', '9.99']
    
    # (2)匹配小数和整数
    strvar = "5.33 3.13 34 34.  .98 9.99 35.5.5sdfsdf  ......"
    lst = re.findall(r"d+(?:.?d*)",strvar)
    print(lst) # ['5.33', '3.13', '34', '34.', '98', '9.99', '35.5', '5']
    
    # 匹配135或171的手机号
    strvar = "asdfasd234 13591199444 17188886666 19145547744"
    lst = re.findall("(?:135|171)d{8}",strvar)
    print(lst) # ['13591199444', '17188886666']
    
    # 卡主开头和结尾,数字必须是11位
    strvar = "13591199444"
    lst = re.findall("^1d{9}d$",strvar)
    print(lst) # ['13591199444']
    
    

    2. search函数:  只要找到一个匹配的值就返回,返回的是一个对象,可以把分组内容和匹配内容全部显示出来

             用对象.group()获取匹配的内容, 用对象.groups获取分组的内容

    
    
    # 匹配www.baidu.com 或者 www.oldboy.com
    strvar = "www.baidu.com"
    lst = re.findall("^www.(?:baidu|oldboy).com$",strvar)
    print(lst) # ['www.baidu.com']
    
    obj = re.search("(www).(baidu|oldboy).(com)",strvar)
    print(obj)  # <_sre.SRE_Match object; span=(0, 13), match='www.baidu.com'>
    print(obj.group())  # www.baidu.com
    print(obj.groups())  # ('www', 'baidu', 'com')
    
    # 获取第一个小括号里面的内容
    print(obj.group(1)) # www
    # # 获取第二个小括号里面的内容
    print(obj.group(2)) # baidu
    # # 获取第三个小括号里面的内容
    print(obj.group(3)) # com
    
    # # ### 案例:用正则做运算   "5*6-7/3" 匹配 5*6 或者 7/3
    # """search 在匹配不到时,返回的是None,无法使用group"""
    # # 匹配出5*6
    strvar = "5*6-7/3"
    # # 匹配出5*6
    obj = re.search(r"d+[*/]d+",strvar)
    print(obj)
    strvar1 = obj.group()
    print(strvar1) # 5*6
    # 按照*号分隔,算出乘积结果
    n1,n2 = strvar1.split("*")
    res1 = int(n1)*int(n2)
    print(res1)
    
    # 对字符串进行替换
    # strvar = "30-7/3"
    strvar2 = strvar.replace(strvar1,str(res1))
    print(strvar2) # 30-7/3
    # 匹配出 7/3
    obj = re.search(r"d+[*/]d+",strvar2)
    strvar3 = obj.group()
    print(strvar3) # 7/3
    # 按照/号分隔,算出除法结果
    n1,n2 = strvar3.split("/")
    res2 = int(n1)/int(n2)
    print(res2)
    # 对字符串进行替换
    strvar4 = strvar2.replace(strvar3,str(res2))
    print(strvar4)
    
    # 通过-号进行最后的分隔,算出最后的结果.
    n1,n2 = strvar4.split("-")
    res_finally = float(n1) - float(n2)
    print(res_finally)  # 27.666666666666668
    
    

    2.2 命名分组: 用?P来给匹配条件分组, 后面调用时可以用1, 2... 也可以用(?P=组名)...

    # 分组
    strvar = "<div>明天<是>周六</div>"
    # 当不清楚字符串中含有什么内容时,用.*?进行取代
    lst = re.findall(r"<(.*?)>(.*?)<(.*?)>",strvar)
    print(lst) # [('div', '明天', '是')]
    
    # (1) 反向引用: 将第一个括号得到的值,在1位置处再调用,将第二个括号里得到的值在2的位置处在调用...
    lst = re.findall(r"<(.*?)>(.*?)<(/1)>",strvar)
    print(lst) # [('div', '明天<是>周六', '/div')]
    
    strvar = "a1b2cab"
    obj = re.search(r"(.*?)d(.*?)dc12",strvar)
    print(obj.group()) # a1b2cab
    
    #  (2) 命名分组:用?P给分的小组命名,后面再调用可以继续用1 2...,也可以直接用(?P=组名)
    # 方法一
    strvar = "a1b2cab"
    obj = re.search(r"(?P<t1>.*?)d(?P<t2>.*?)dc12",strvar)
    print(obj.group()) # a1b2cab
    
    # 方法二
    strvar = "a1b2cab"
    obj = re.search(r"(?P<t1>.*?)d(?P<t2>.*?)dc(?P=t1)(?P=t2)",strvar)
    print(obj.group()) # a1b2cab
    3. match()函数:  用法与search()类似,只是在匹配条件前强制加上^, 强制以...开头, 可用于验证用户输入内容
    strvar = "  天空天地"
    obj = re.search("天.",strvar)
    print(obj.group()) # 天空
    obj = re.match("天.",strvar)
    print(obj.group()) # 报错,因字符串时空格开头的,不符合match的匹配条件

    4. split(): 切割,可根据多种条件进行切割

    strvar = "bob-alice&jack%roce-fahai"
    res = re.split("[-&%]",strvar)
    print(res) # ['bob', 'alice', 'jack', 'roce', 'fahai']
    
    strvar = "0525天气晴朗0524天气多云0523天气阴"
    res = re.split("d+",strvar)
    print(res) # ['', '天气晴朗', '天气多云', '天气阴']

    5. sub()和subn():  sub()可根据多个条件进行替换,也能选择替换的次数. subn()与sub()用法一样,只是会把新字符串与替换的次数一起组成元祖返回

    # sub(): 可根据多个条件进行替换,也能选择替换的次数
    strvar = "bob-alice&jack%roce-fahai"
    res = re.sub("[-%&]","#",strvar)
    print(res) # bob#alice#jack#roce#fahai
    
    res = re.sub("[-%&]","#",strvar,2)
    print(res) # bob#alice#jack%roce-fahai  替换两次
    
    # subn(): 与sub()用法一样,只是会把新字符串与替换的次数一起组成元祖返回
    strvar = "bob-alice&jack%roce-fahai"
    res = re.subn("[-%&]","#",strvar)
    print(res) # ('bob#alice#jack#roce#fahai', 4)
    
    strvar = "bob-alice&jack%roce-fahai"
    res = re.subn("[-%&]","#",strvar,2)
    print(res) # ('bob#alice#jack%roce-fahai', 2)

    6.  finditer():  匹配字符串中的内容,返回迭代器,适用于大量数据的匹配

    strvar = "0525天气晴朗0524天气多云0523天气阴"
    it = re.finditer("d+",strvar)
    obj = next(it)
    print(obj.group()) # 0525
    obj = next(it)
    print(obj.group()) # 0524
    
    strvar = "0525天气晴朗0524天气多云0523天气阴"
    it = re.finditer("d+",strvar)
    for i in it:
        print(i.group())
    # 0525
    # 0524
    # 0523

    7.  compile():  指定一个统一的匹配规则,可以定义一次匹配规则,终身使用,无需反复定义,节约系统资源

    pattern = re.compile("d+")
    strvar = "0525天气晴朗0524天气多云0523天气阴"
    res = pattern.findall(strvar)  # 只需传字符串
    print(res) # ['0525', '0524', '0523']
    
    str1 = "数学97语文88英语90"
    res = pattern.findall(str1)
    print(res) # ['97', '88', '90']
    
    obj = pattern.search(str1)
    res = obj.group()
    print(res) # 97

    8. 修饰符: re.I   re.M  re.S

    # (1) re.I : 使匹配条件对大小写不敏感
    strvar = "<h1>How Are You</H1>"
    obj = re.search("<h1>(.*?)</h1>",strvar,flags=re.I)
    print(obj.group())
    
    # (2) re.M : 使每一行都可以单独匹配,影响^和$
    strvar = """<h1>123</H1>
    <p>123</p>
    <div>123</div>
    """
    res = re.findall("^<.*?>(?:.*?)<.*?>$",strvar)
    print(res) # []
    res = re.findall("^<.*?>(?:.*?)<.*?>$",strvar,flags=re.M)
    print(res) # ['<h1>123</H1>', '<p>123</p>', '<div>123</div>']
    
    # (3) re.S: 匹配包括换行符在内的所有字符
    strvar = """give
    1112233mefive
    """
    pattern = re.compile(".+five")
    res = pattern.findall(strvar)
    print(res) # ['1112233mefive']
    pattern = re.compile(".+five",flags=re.S)
    res = pattern.findall(strvar)
    print(res) # ['give
    1112233mefive']

     9. 正则案例之正则计算器:

    strvar = "1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))"
    import re
    
    def sign_exp(strvar):  # 式子的优化
        strvar = strvar.replace("++","+")
        strvar = strvar.replace("--","+")
        strvar = strvar.replace("+-","-")
        strvar = strvar.replace("-+","-")
        return strvar
    
    def calc_exp(strvar):
          # 乘法除法的计算
        if "*" in strvar:
            a, b = strvar.split("*")
            return float(a) * float(b)
        if "/" in strvar:
            a, b = strvar.split("/")
            return float(a) / float(b)
    
    def opreate_exp(strvar):  # (40+5*-2+3/2)
        while True:
            obj =  re.search(r"d+(.d+)?[/*][+-]?d+(.d+)?",strvar)  # 找出式子里第一个乘法或者除法式子
            if obj:
                res1 = obj.group()
                res2 = calc_exp(res1)  # 计算乘法或者除法的结果
                strvar = strvar.replace(res1,str(res2))   # 将结果替换进式子里
            else:
                break
        strvar = sign_exp(strvar)  # 优化式子
        lst = re.findall("[+-]?d+(?:.d+)?",strvar) # 做加减法的累加
        total = 0
        for i in lst:
            total += float(i)
        return total  # 返回结果
    
    def remove_bracket(strvar):  # strvar = "-30+(40+5*-2+3/2)*8+(4-7)"
        while True:
            obj = re.search("([^()]+)",strvar)  # 匹配出括号里的式子
            if obj:
                res1 = obj.group()
                # print(res1)  # (40+5*-2+3/2)
                res2 = opreate_exp(res1)   # 做乘除法
                strvar = strvar.replace(res1,str(res2))  # 将乘除法的结果替换进字符串
            else:
                return strvar  # 返回没有括号的字符串
    
    def main(strvar):
        strvar = strvar.replace(" ","")  # 将字符串里空格去掉
        strvar = remove_bracket(strvar)  # 清除小括号
        return opreate_exp(strvar)
    
    res = main(strvar)
    print(res)
     
  • 相关阅读:
    大二第二学期周学习进度总结(七)
    java课程之团队开发冲刺阶段1.1
    Java课程之团队开发(NABCD需求分析)
    大二第二学期周学习进度总结(六)
    Java课程之团队开发(团队介绍)
    大二第二学期周学习进度总结(五)
    模拟退火 费马点求解
    三分 传送带
    2357数
    B监狱 noip 模拟 7.29(区间DP)
  • 原文地址:https://www.cnblogs.com/fdsimin/p/12940310.html
Copyright © 2011-2022 走看看