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())#打印匹配的内容 '.' 默认匹配除\n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行 '^' 匹配字符开头,若指定flags MULTILINE,这种也可以匹配上(r"^a","\nabc\neee",flags=re.MULTILINE) '$' 匹配字符结尾,或e.search("foo$","bfoo\nsdfsf",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") 是匹配不到的 '\Z' 匹配字符结尾,同$ '\d' 匹配数字0-9 '\D' 匹配非数字的所有字符 '\w' 匹配[A-Za-z0-9] '\W' 匹配非[A-Za-z0-9] '\s' 匹配空白字符、\t、\n、\r , re.search("\s+","ab\t\n \r")结果:'\t\n \r'> '(?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'} 总结: + 表示 会按照它前面字符的样式来打印多个 . 表示 打印除\n(换行)外的所有字符 .+ 组合才会全部包括后面的数字 打印之后的所有字符 [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]\Z","123a")#结果:'123a' print(ser3) ser4=re.search("\s+","ab\t\n \r")#结果:'\t\n \r' 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("wang\d+","wang234 mazi ") print(res.group())""" """ . 的用法 res =re.match(".","@wang234 mazi ")# . 默认匹配除\n之外的任意一个字符 在此处打印 @ # 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 然后 . 表示一个除\n(换行)外的任意一个字符取出空格, 第二个加号表示 从 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]+\Z","123sdf")#\A等同于 ^ ,表示从第一个元素开始,从第一个为数字,然后经过几个数,然后经过几个字母\Z表示以 字母结束 res =re.search("\D+","123&%*- A@ \\n") #\D匹配不是数字的任意一个字符 特殊字符可以 换行也可以 结果为:&%*- A@ \n res =re.search("\w+","123&%*- A@ \\n")# 小写的 \w只匹配数字和字母 结果为:123 res =re.search("\W+","123&%*- A@ \\n")#只匹配特殊字符 结果为:&%*- #res =re.search("\s+","\r\t\n123&%*- 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("\033[33;1m减号[%s]处理结果:\033[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("\033[31;1m[%s]运算结果=\033[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("\033[32;1m[%s]运算结果:\033[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('\033[41;1m----没拓号了...---\033[0m') print('\n\n\033[42;1m最终结果:\033[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) )")