zoukankan      html  css  js  c++  java
  • python,re模块正则

    python没有正则需要导入re模块调用.正则表达式是为了匹配字符串,动态模糊的匹配,只要有返回就匹配到了, 没返回就没匹配到,前面是格式后面是字符串
    最常用的匹配语法:
    re.match()#从头开始匹配(两种方式:简单,分组)
    re.search()#浏览全部字符,匹配第一个符合规则的字符串
    re.findall()#把所有匹配到的字符放到以列表中的元素返回
    re.split()#以匹配到的字符当做列表分隔符
    re.sub()#匹配字符并替换
    re.finditer()    

    扩展:
    re.I(re.IGNORECASE): 忽略大小写(括号内是完整写法,下同)
    M(MULTILINE): 多行模式,改变'^''$'的行为
    S(DOTALL): 点任意匹配模式,改变'.'的行为
    
    import re
    res=re.match('^zc','zcok168')
    print(res)
    print(res.group())#打印匹配的内容
    
    '.'     默认匹配除
    之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行
    '^'     匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","
    abc
    eee",flags=re.MULTILINE)
    '$'     匹配字符结尾,或e.search("foo$","bfoo
    sdfsf",flags=re.MULTILINE).group()也可
    '*'     匹配*号前的字符0次或多次,re.findall("ab*","cabb3abcbbac")  结果为['abb', 'ab', 'a']
    '+'     匹配前一个字符1次或多次,re.findall("ab+","ab+cd+abb+bba") 结果['ab', 'abb']
    '?'     匹配前一个字符1次或0次
    '{m}'   匹配前一个字符m次
    '{n,m}' 匹配前一个字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 结果'abb', 'ab', 'abb']
    '|'    匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 先匹配第一个结果'ABC',如果使用findall就没有group()方法
    '(...)' 分组匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 结果 abcabca456c
    'A'    只从字符开头匹配,re.search("Aabc","alexabc") 是匹配不到的
    ''    匹配字符结尾,同$
    'd'    匹配数字0-9
    'D'    匹配非数字的所有字符
    'w'    匹配[A-Za-z0-9]
    'W'    匹配非[A-Za-z0-9]
    's'    匹配空白字符、	、
    、
     , re.search("s+","ab	
      
    ")结果:'	
      
    '>
    '(?P<name>...)' 分组匹配 re.search("(?P<province>[0-9]{4})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242").groupdict("city")结果: {'province': '3714', 'city': '81', 'birthday': '1993'}
    
    总结:
    + 表示 会按照它前面字符的样式来打印多个
    . 表示 打印除
    (换行)外的所有字符
    .+ 组合才会全部包括后面的数字 打印之后的所有字符
    [a-z] 表示 打印一个小写字母;[A-Z]表示:打印一个大写字母
    [a-z] + [A-Z] 可以组合起来用
    Eg:("z[a-z]+[A-Z]+","jiang123zhongzHenzhongzhen1232424124zhongzhen")
    一、z[a-z]+[A-Z]+.+ 就是将上面从z开始打印完     结果:zhongzHenzhongzhen1232424124zhongzhen
    二、"z[a-zA-Z]+d+" 就是将上面从z开始打印到结果:zhongzHenzhongzhen1232424124
    练习例子:
    import re
    ser=re.search("aal?","aaexaaaa")#匹配问号前面一个字符一次或0次,如果问号前面字符匹配不到会匹配到后面,结果:aa    
    print(ser)
    
    ser1=re.search("[0-9]{3}","aa1x2a345aa")#匹配前一个字符M次,结果:345
    print(ser1)
    
    ser1=re.findall("[0-9]{1,3}","aa1x2a345aa")#匹配所有字符放到列表中返回,结果:['1', '2', '345']
    print(ser1)
    
    ser2=re.search("(abc){2}(||=){2}",'alexabcabc||=||=')#需要来转义,结果:'abcabc||=||='
    print(ser2)
     
    ser3=re.search("A[0-9]+[a-z]","123a")#结果:'123a'
    print(ser3)
    
    ser4=re.search("s+","ab	
      
    ")#结果:'	
      
    '
    print(ser4)
    
    ser5=re.search("(?P<id>[0-9]+)(?P<name>[a-zA-Z]+)","abcd1234daf@34").groupdict('name')
    print(ser5)#结果:{'id': '1234', 'name': 'daf'}
    
    ser6=re.search("(?P<province>[0-9]{3})(?P<city>[0-9]{3})(?P<birthday>[0-9]{4})","610331198908071513").groupdict()
    print(ser6)#分组匹配,{'province': '610', 'city': '331', 'birthday': '1989'}
    
    ser6=re.split("[0-9]+","abc12de3f45GH")
    print(ser6)#按数字进行分割,['abc', 'de', 'f', 'GH']
    
    ser7=re.sub("[0-9]+","|","abc12de3f45GH",count=2)#count=2也和写成2
    print(ser7)#匹配字符并替换所有数字,加count=2只匹配前2个,abc|de|f45GH
    
    ser8=re.search("[a-z]+","abcdE",flags=re.I)
    print(ser8)#大小写都匹配,'abcdE'
    
    重点知识:
    res=re.search("aaaaz?","azhangaaaa")# 表示 ?前面的那个 z有和没有都可以  但是z?前面的那些a必须都要匹配到,如果匹配不到就 报错,可以匹配到就输出
    res =re.findall("[0-9]{1,3}","z1h23a456n7g8")#re.findall()  没有group方法
    print(res)#结果为:['1', '23', '456', '7', '8']
    res =re.findall("[0-9]{1,2}","z1h23a456n7g8")
    print(res)#结果为:['1', '23', '45', '6', '7', '8']
    res =re.findall("[0-9]{3}","z1h23a456n7g8")
    rint(res)#结果为:['456']
    
    res=re.search("(?P<province>[0-9]{2})(?P<shi>[0-9]{2})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242")
    print(res.groupdict())   #其中的 ?P 表示语法 <key>[范围]{几位}   结果为:{'province': '37', 'shi': '14', 'city': '81', 'birthday': '1993'}  并且还可以再加几组字典
    print(res.groupdict()['city']) #  相当于取出字典中的key=’city’结果为:81
    re模块用法案例
    res =re.search("[a-z]+","zhangSHuai",flags =re.I)# flag =re.I 忽略大小写  结果为:zhangSHuai
    print(res.group())
    
    """re(正则表达式)就是用于动态匹配的 如果是一个固定值,就不需要通过re来进行    直接通过  wang  in  wangmazi:就可以进行匹配 """
    
    import re
    """re.match 的用法:就是默认从头开始的,
    ^ 表示要匹配字符开头 故而 ^ 在match中没有用
    第一个""写的是要匹配的内容,后面的""写的是匹配度的范围
    res =re.match("^wang","wang mazi")
    print(res)  #如果有返回结果 就表示匹配到了  如果没有匹配到就返回 None
    print(res.group())#通过res.group()来查看匹配到什么"""
    
    """ d+的用法
     表示后面是用于正则的语法,d表示一个数字 结果为:wang2,
    d+表示一个或多个数字结果为:wang234
    res =re.match("wangd+","wang234 mazi ")
    print(res.group())"""
    
    """   . 的用法
    res =re.match(".","@wang234 mazi ")#  . 默认匹配除
    之外的任意一个字符  在此处打印 @
    # res =re.match(".+","wang234 mazi ")# + 表示打印后面的多个 故而: .+ 打印全部
    # res =re.match(".d","w1ang234 mazi ")#如果第一位是 w 第二个为数字就可以执行,否则就会报错
    # res =re.match("^w","wang234 mazi ")
    print(res.group())"""
    
    """re.serach的用法  表示从整个内容中搜查 这是会用到 ^ 符号"""
    #res = re.search("z.+n","jiang123zhongzhen123a")#从z开始 通过.+就z之后一直到
    #后面的 n 如果前面+之后没有n就会包括123
    
    #res =re.search("z[a-z]+.+2","jiang123zhong zhen123a")
    """
    [a-z]输出一个在a到z之间的一个字符, + 表示多个字符,第一个 + 从o取到g
    然后 . 表示一个除
    (换行)外的任意一个字符取出空格, 第二个加号表示
    从 z 一直往后取到加号后面的截止字符 结果为:zhong zhen12
    res =re.search("z[a-z]+[A-Z]+.+","jiang123zhongzHenzhongzhen1232424124zhongzhen")#输出结果为:zhongZhenzhongzhen
    #res =re.search("z[a-zA-Z]+d+","jiang123zhongzHenzhongzhen1232424124zhongzhen")
    res =re.search("#.+#","123#hello#")#结果为:#hello#
    print(res.group())"""
    # res=re.search("aaaaa?","azhangaaaa")#表示?前面的那个a有和没有都可以 但是a?前面的那些a必须要匹配到
    # print(res.group())
    
    """re.findall() 匹配不相连的多个数字  并且没有group()方法
    #res =re.findall("[0-9]{1,2}","z1h23a456n7g8")#结果为:['1', '23', '45', '6', '7', '8']
    #res =re.findall("[0-9]{1,3 }","z1h23a456n7g8")#结果为:['1', '23', '456', '7', '8']
    res =re.findall("[0-9]{3}","z1h23a456n7g8")#结果为:['456']
    print(res)"""
    
    res=re.search("abc|ABC","ABCBabcdB")#先匹配小写或者再匹配大写  返回结果:ABC
    res=re.search("abc{2}","abccadf") #匹配abc并且c匹配两次 即:必须要有abcc才可以才返回,否则报错
    res =re.search("(abc){2}","abcabcadf")#同上 将abc当做一个小组,同时匹配两次 即:abcabc 否则报错
    res =re.search("(abc){2}|","abcabcadf")#同理  表示转义符,代表不要将 |当做或l来处理 有abcabc| 时才输出,否则报错
    res =re.search("(abc){2}(||=){2}","sdabcabc||=||=adf")# 每一个 | 都要用输出结果为:abcabc||=||=
    res =re.search("A[0-9]+[a-z]+","123sdf")#A等同于 ^ ,表示从第一个元素开始,从第一个为数字,然后经过几个数,然后经过几个字母表示以 字母结束
    res =re.search("D+","123&%*- A@ \n") #D匹配不是数字的任意一个字符  特殊字符可以 换行也可以 结果为:&%*- A@ 
    
    res =re.search("w+","123&%*- A@ \n")# 小写的 w只匹配数字和字母 结果为:123
    res =re.search("W+","123&%*- A@ \n")#只匹配特殊字符 结果为:&%*-
    #res =re.search("s+","
    	
    123&%*- A@ ")
    res=re.search("(?P<province>[0-9]{2})(?P<shi>[0-9]{2})(?P<city>[0-9]{2})(?P<birthday>[0-9]{4})","371481199306143242")
    #其中的 ?P 表示语法 <key>[范围]{几位}   结果为:{'province': '37', 'shi': '14', 'city': '81', 'birthday': '1993'}
    print(res.groupdict()['city'])
    res =re.split("[0-9]+","ab2h4h35g42g") # 因为[0-9]只是一个字符,故而表示将后面的内容# 以数字分隔开,然后是单个数字的去掉,
    多个数字的就以空字符显示出来并与分隔开的字母形成列表   结果为:['ab', 'h', 'h', '', 'g', '', 'g']
    res =re.sub("[0-9]+","|","ab2h4h35g42g",count=2)
    print(res)
    res =re.search("[a-z]+","zhangSHuai",flags =re.I)# flag =re.I 忽略大小写  结果为:zhangSHuai
    print(res.group())
    计算器作业
    1.    实现加减乘除及拓号优先级解析
    2.    用户输入 1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )等类似公式后,必须自己解析里面的(),+,-,*,/符号和公式(不能调用eval等类似功能偷懒实现),运算后得出结果,结果必须与真实的计算器所得出的结果一致
    3.    import re
    import functools
    def minus_operator_handler(formula):
        '''处理一些特殊的减号运算'''
        minus_operators = re.split("-", formula)
        calc_list = re.findall("[0-9]", formula)
        if minus_operators[0] == '':  # 第一值肯定是负号
            calc_list[0] = '-%s' % calc_list[0]
        res = functools.reduce(lambda x, y: float(x) - float(y), calc_list)
        print("33[33;1m减号[%s]处理结果:33[0m" % formula, res)
        return res
    
    def remove_duplicates(formula):
        formula = formula.replace("++", "+")
        formula = formula.replace("+-", "-")
        formula = formula.replace("-+", "-")
        formula = formula.replace("--", "+")
        formula = formula.replace("- -", "+")
        return formula
    
    def compute_mutiply_and_dividend(formula):
        '''算乘除,传进来的是字符串噢'''
        operators = re.findall("[*/]", formula)
        calc_list = re.split("[*/]", formula)
        res = None
        for index, i in enumerate(calc_list):
            if res:
                if operators[index - 1] == "*":
                    res *= float(i)
                elif operators[index - 1] == "/":
                    res /= float(i)
            else:
                res = float(i)
    
        print("33[31;1m[%s]运算结果=33[0m" % formula, res)
        return res
    
    def handle_minus_in_list(operator_list, calc_list):
        '''有的时候把算术符和值分开后,会出现这种情况  ['-', '-', '-'] [' ', '14969037.996825399 ', ' ', '12.0/ 10.0 ']
           这需要把第2个列表中的空格都变成负号并与其后面的值拼起来,
        '''
        for index, i in enumerate(calc_list):
            if i == '':  # 它其实是代表负号,改成负号
                calc_list[index + 1] = i + calc_list[index + 1].strip()
    
    def handle_special_occactions(plus_and_minus_operators, multiply_and_dividend):
        '''有时会出现这种情况 , ['-', '-'] ['1 ', ' 2 * ', '14969036.7968254'],2*...后面这段实际是 2*-14969036.7968254,需要特别处理下'''
        for index, i in enumerate(multiply_and_dividend):
            i = i.strip()
            if i.endswith("*") or i.endswith("/"):
                multiply_and_dividend[index] = multiply_and_dividend[index] + plus_and_minus_operators[index] + 
                                               multiply_and_dividend[index + 1]
                del multiply_and_dividend[index + 1]
                del plus_and_minus_operators[index]
        return plus_and_minus_operators, multiply_and_dividend
    
    def compute(formula):
        '''这里计算是的不带括号的公式'''
    
        formula = formula.strip("()")  # 去除外面包的拓号
        formula = remove_duplicates(formula)  # 去除外重复的+-号
        plus_and_minus_operators = re.findall("[+-]", formula)
        multiply_and_dividend = re.split("[+-]", formula)  # 取出乘除公式
        if len(multiply_and_dividend[0].strip()) == 0:  # 代表这肯定是个减号
            multiply_and_dividend[1] = plus_and_minus_operators[0] + multiply_and_dividend[1]
            del multiply_and_dividend[0]
            del plus_and_minus_operators[0]
    
        plus_and_minus_operators, multiply_and_dividend = handle_special_occactions(plus_and_minus_operators,
                                                                                    multiply_and_dividend)
        for index, i in enumerate(multiply_and_dividend):
            if re.search("[*/]", i):
                sub_res = compute_mutiply_and_dividend(i)
                multiply_and_dividend[index] = sub_res
        # 开始运算+,-
        print(multiply_and_dividend, plus_and_minus_operators)
        total_res = None
        for index, item in enumerate(multiply_and_dividend):
            if total_res:  # 代表不是第一次循环
                if plus_and_minus_operators[index - 1] == '+':
                    total_res += float(item)
                elif plus_and_minus_operators[index - 1] == '-':
                    total_res -= float(item)
            else:
                total_res = float(item)
        print("33[32;1m[%s]运算结果:33[0m" % formula, total_res)
        return total_res
    
    def calc(formula):
        '''计算程序主入口, 主要逻辑是先计算拓号里的值,算出来后再算乘除,再算加减'''
        parenthesise_flag = True
        calc_res = None  # 初始化运算结果为None,还没开始运算呢,当然为None啦
        while parenthesise_flag:
            m = re.search("([^()]*)", formula)  # 找到最里层的拓号
            if m:
                # print("先算拓号里的值:",m.group())
                sub_res = compute(m.group())
                formula = formula.replace(m.group(), str(sub_res))
            else:
                print('33[41;1m----没拓号了...---33[0m')
    
                print('
    
    33[42;1m最终结果:33[0m', compute(formula))
                parenthesise_flag = False  # 代表公式里的拓号已经都被剥除啦
    
    if __name__ == '__main__':
        # res = calc("1 - 2 * ( (60-30 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )")
        res = calc(
            "1 - 2 * ( (60-30 +(-9-2-5-2*3-5/3-40*4/2-3/5+6*3) * (-9-2-5-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )")
  • 相关阅读:
    连通图是不是欧拉图
    P1127 词链 题解
    ClickHouse的JDBC连接
    ClickHouse集群搭建和使用
    ClickHouse引擎
    ClickHouse 的安装和使用
    SNMP3安装
    解决springboot打不出业务log
    如何用电脑下载微信视频号中的视频?
    【Swing】如何打开文件选择对话框,选择文件
  • 原文地址:https://www.cnblogs.com/zcok168/p/9142074.html
Copyright © 2011-2022 走看看