Python全栈--6.1-match-search-findall-group(s)的区别以及计算器实例
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python全栈--6.1-match-search-findall-group(s)的区别以及计算器实例相关的知识,希望对你有一定的参考价值。
match、search、findall、group(s) 区别
import re # match findall经常用 # re.match() #从开头匹配,没有匹配到对象就返回NONE # re.search() #浏览全部字符,匹配第一个符合规则的字符串 # re.findall() # 将匹配到的所有内容都放置在一个列表中
一、match有两种情况
------- 有分组 ------取匹配到的正则再次取其部分内容
origin = "hello alex sadf dsaf" r = re.match("(h)\\w+",origin) print(r.group()) # hello 获取匹配所有结果 print(r.groups()) #(\'h\',) #获取模型中匹配到的分组 没有分组则为空元组 r = re.match("(?P<n1>h)(?P<n2>\\w+)",origin) #获取模型中匹配到的分组中所有执行力key的组 ?P<KEY>VALUE {\'n2\': \'ello\', \'n1\': \'h\'} print(r.groupdict()) #?P<KEY>VALUE {\'n2\': \'ello\', \'n1\': \'h\'}
------- 无分组 ------
r = re.match("h\\w+",origin) print(r.group()) # 获取匹配所有结果 hello print(r.groups()) #获取模型中匹配到的分组 () print(r.groupdict()) #获取模型中匹配到的分组 {}
二、groups、group、groupdict
print(r.group()) # hello 获取匹配所有结果 print(r.groups()) #(\'h\',) #获取模型中匹配到的分组 没有分组则为空元组 r = re.match("(?P<n1>h)(?P<n2>\\w+)",origin) #获取模型中匹配到的分组中所有执行力key的组 ?P<KEY>VALUE {\'n2\': \'ello\', \'n1\': \'h\'} print(r.groupdict()) #?P<KEY>VALUE {\'n2\': \'ello\', \'n1\': \'h\'}
三、search两种情况
search 不用从开头匹配,而是匹配全局整个字符串,一旦又符合就退出
------- 有分组 ------
origin = "hello alex alix bcd dsfa lefg abc 199" r = re.search("a(\\w+)",origin) print(r.group()) #alex print(r.groups()) #(\'lex\',) r = re.search("(?P<key1>a)(?P<key2>(\\w+))",origin) print(r.groupdict()) #{\'key1\': \'a\', \'key2\': \'lex\'}
------- 无分组 ------
origin = "hello alex alix bcd dsfa lefg abc 199" r = re.search("ali\\w+",origin) print(r.group()) #alix print(r.groups()) #() print(r.groupdict()) #{}
四、findall
# 1 匹配到之后,就抽离,继续从下一个字符开始匹配
origin = "a2b3c4d5" a=re.findall("\\d+\\w\\d+",origin) #[\'2b3\', \'4d5\'] print(a)
# 2 空值也会挨个字符去匹配,结尾后,还要继续多匹配一次
num = "asd" print(re.findall("",num)) # [\'\', \'\', \'\', \'\']
# 无分组
origin = "hello alex alix bcd dsfa lefg abc 199" print(re.findall("a\\w+",origin)) # [\'alex\', \'alix\', \'abc\'] print(re.findall("(a\\w+)",origin)) #[\'alex\', \'alix\', \'abc\'] print(re.findall("a(\\w+)",origin)) #组 groups [\'lex\', \'lix\', \'bc\'] print(re.findall("(a)(\\w+)(x)",origin)) # [(\'a\', \'le\', \'x\'), (\'a\', \'li\', \'x\')] 将 三个分组匹配到的做成元组 放到列表作为一个元素
findall 的特点
分组匹配 * 贪婪匹配: 比如如下的asd 为一个分组,而一旦遇到asd开始的字符串,如果 后面还是asd也会匹配,这就是贪婪匹配。 findall 特性: 1 有几个分组返回几个内容:,并将返回内容放到元组内 作为列表的一个元素。 2 即尽管* 匹配到了两个asd ,但是因为是贪婪虚拟匹配出的,有一个分组,所以, 只会,取一个。 3 而findall默认只取最后一组匹配的内容,故此 只返回最后一组asd 4 findall 如果正则能有空的匹配的话,那么匹配字符串最后还会匹配到一个空 5 多个分组匹配到做成元组,当成列表的一个元素 6 多个分组,查找顺序,外到内,左到右 ((\\w)(\\w)){2,} 先是找到2个字母的,再在这两个字母里面进行局部分组
# 1 特性 1 2 3 4
print(re.findall(r\'(asd)*\',\'asdasd\')) #[\'asd\', \'\']
# 2 如下,默认+可以第一次 就匹配到 1asd2asd 但由于前面只有1个分组,只能返回后面的4位了
n = re.findall("(\\dasd)+","1asd2asdp2asds") # [\'2asd\', \'2asd\'] print(n)
# 3 如下,默认*可以第一次 就匹配到 1asd2asd 但由于前面只有1个分组,只能返回后面的4位了
#但是*还可以表示0次,故再遇到p的时候,空就能匹配了,而且,最后还有个s也匹配到空,结尾还默认还会匹配到空
n = re.findall("(\\dasd)*","1asd2asdp2asds") # [\'2asd\', \'\', \'2asd\', \'\', \'\'] print(n)
#4 匹配,最多四个字母,因此alex都找到了,但是只有一个分组,所以只返回最后一个\\w故x
a = "alex" n = re.findall("(\\w){4}",a) print(n) # [\'x\']
#5 这里findall 匹配分组是一个字母匹配到了,而*是贪婪匹配,四个字母都匹配就取到了四个字母,而正则分组只有一个,因此只取最后一个
a = "alex" n = re.findall("(\\w)*",a) print(n) # [\'x\', \'\']
#6 由于从外到内, 所以匹配两个字母的 al 匹配到了,ex也匹配到了,外部分组1个,因此ex,而内部从左到右又会匹配。
a = "alex" n = re.findall("((\\w)(\\w)){2,}",a) print(n) # [(\'ex\', \'e\', \'x\')]
#7 会匹配ax alex alex acd 但是贪婪匹配的分组只有 1个 因此 ax ax ax ad
origin = "hello ax lex bed alex lge alex acd 19" n = re.findall("(a)(\\w)*" , origin) print(n) #[(\'a\', \'x\'), (\'a\', \'x\'), (\'a\', \'x\'), (\'a\', \'d\')]
实例 Python编写计算器
#!/usr/bin/env python # _*_ coding:utf-8 _*_ import re,time def compte_add_sub(inp): arg = inp[0] # 传入的只剩下 加减的字符串为列表 获取第一个值 if arg.find("+-") != -1 or arg.find("-+") != -1: arg = arg.replace("+-","-",len(arg)) arg = arg.replace("-+","-",len(arg)) elif arg.find("++") != -1 or arg.find("--") != -1: arg = arg.replace("++","+",len(arg)) arg = arg.replace("--","+",len(arg)) arg = re.findall("[\\+\\-]|\\d+\\.?\\d*",arg) # if arg[0] == "-": arg[0]=arg[0]+arg[1] del arg[1] add_sum = float(arg[0]) for i in range(1,len(arg),2): if arg[i] == "+": add_sum +=float(arg[i+1]) elif arg[i] == "-": add_sum -= float(arg[i+1]) return add_sum #处理乘除 def compute_mul_div(arg): arg = arg[0] end =len(arg) ###########计算平方########## arg = re.sub("(//)","/",arg) #print(arg) while True: x = re.search("\\d+\\.*\\d*(\\*\\*)\\d+\\.*\\d*",arg) if x: expre = x.group() print(expre) x = x.group().split("**") ret = float(x[0]) ** float(x[-1]) if "e" in str(ret): ret=int(ret) #print(ret) arg = arg.replace(expre,str(ret),1) print(arg) else: #print("exit") break ###########计算平方########## li = re.findall(r"[*/]",arg) num = len(li) for i in range(num): new = arg.split(li[i],1) la=re.findall("[\\+\\-\\/]?(\\d+\\.?\\d*)",new[0])[-1] sta = re.findall("([\\+\\-\\/]?\\d+\\.?\\d*)",new[1])[0] if li[i] == "*": new_che = float(la) * float(sta) else: new_che = float(la) / float(sta) arg = new[0][0:-len(la)] + str(new_che) +new[1][len(sta):] arg=[arg,] return compte_add_sub(arg) def comput(expression): inp = [expression,] n= compute_mul_div(inp) return n def excut(expression): kuohao=[] if expression.find("(") == -1: ret = comput(expression) return ret for i in range(len(expression)): if "(" == expression[i]: kuohao.append(i) elif ")" == expression[i]: ans_kuo = expression[kuohao[-1]+1:i] ret_num = comput(ans_kuo) expression = expression[0:kuohao[-1]]+str(ret_num)+expression[i+1:] return excut(expression) def main(): a = \'1 - 2 * ((60-30 +(1-40/5*5+3-2*5/3) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2))\' default = \'1-40/5*5+3-2*5/3\' a = default if len(a) == 0 else re.sub("\\s*", \'\', a) # 三元运算给a默认值,否则 给表达式去除空格 ret = excut(a) # 调用excut 方法 并将返回值给ret print("\\033[33;1m公式为:\\033[0m",a) print("\\033[35;1m结果为:\\033[0m",ret) if __name__ == \'__main__\': start = time.clock() main() end = time.clock() print("read: %f s" % (end - start))
结果
C:\\Python35\\python3.exe E:/py_test/s3_py/real_cal_liujianzuo.py 公式为: 1-2*((60-30+(1-40/5*5+3-2*5/3)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2)) 结果为: 13652214.56825397 read: 0.001188 s
version1
#!/usr/bin/env python # _*_ coding:utf-8 _*_ import re def compte_add_sub(inp): # inp = [\'-9-8.8++9--9\',] arg = inp[0] # 传入的只剩下 加减的字符串为列表 获取第一个值 #去除++ +- -- -+ if arg.find("+-") != -1 or arg.find("-+") != -1: arg = arg.replace("+-","-",len(arg)) arg = arg.replace("-+","-",len(arg)) elif arg.find("++") != -1 or arg.find("--") != -1: arg = arg.replace("++","+",len(arg)) arg = arg.replace("--","+",len(arg)) new_m = re.search(\'[\\-]*\\d+\\.*\\d*[\\-\\+]+\\d+\\.*\\d*\',arg) # 匹配 -9.9 + 9.9 或者 -9.9 - 9.9 if not new_m: # print(arg) return arg # 递归处理,当匹配不到上面的表达式就将表达式结果返回 即处理加减后的结果 else: brefor,after = re.split(\'[\\-]*\\d+\\.*\\d*[\\+\\-]+\\d+\\.*\\d*\',arg,1) #以匹配到的表达式为分隔符 分割 new_m=new_m.group() #定义成列表 将匹配到的表达式 if new_m.find("+") != -1: #如果匹配的是+号 new_m=new_m.split("+") #以+号分割 # print(new_m) zhi = float(new_m[0]) + float(new_m[1]) #计算加号 else: #减号的话 if new_m.startswith("-"): #如果匹配到的表达式以减号开头 #对应的序列元素第一个是空 new_m=new_m.split("-") #以减号分割 zhi = -(float(new_m[1]) + float(new_m[2])) #提出减号 内部相加即可 # print(zhi) else: #如果不以减号开头则 直接按分割收的序列 new_m=new_m.split("-") # print(new_m) zhi = float(new_m[0]) - float(new_m[1]) #zhi = float(\'%0.6f\'%zhi) #浮点数优化精度 #print(zhi) arg = brefor + str(zhi) +after #字符串类型进行拼接 # print(arg) inp = [arg,] #更改列表 # print(inp) return compte_add_sub(inp) #处理乘除 def compute_mul_div(arg): #arg = [\'9-2*5/3+7/3*99/4*2998+10*568/14\', 0] val = arg[0] #取出表达式 ###########计算平方########## val = re.sub("(//)","/",val) #print(arg) while True: x = re.search("\\d+\\.*\\d*(\\*\\*)\\d+\\.*\\d*",val) if x: expre = x.group() print(expre) x = x.group().split("**") ret = float(x[0]) ** float(x[-1]) if "e" in str(ret): ret=int(ret) #print(ret) val = val.replace(expre,str(ret),1) print(val) else: #print("exit") break ###########计算平方########## mch = re.search(\'\\d+\\.*\\d*[\\*\\/]+[\\+\\-]?\\d+\\.*\\d*\', val) # 由于递归,首先判断传入的表达式满足要求与否, 例子: 9.9 * 9.8 或者 9.9 /9.8 是否包含。 if not mch: return #退出函数 因为arg是列表与comput的inp列表指向的同一个内存地址,故不需要返回值 content = re.search(\'\\d+\\.*\\d*[\\*\\/]+[\\+\\-]?\\d+\\.*\\d*\', val).group() #存在 例子: 9.9 * 9.8 或者 9.9 /9.8 的话取出 if len(content.split(\'*\')) > 1: # 判断是否* 进行分割查看长度,有*的话则会大于1 没有就是/ n1, n2 = content.split(\'*\') value = float(n1) * float(n2) else: n1, n2 = content.split(\'/\') value = float(n1) / float(n2) #value = float(\'%0.7f\'%value) #float 类型取7个精度 即小数点后7位,否则太长影响效率 before, after= re.split(\'\\d+\\.*\\d*[\\*\\/]+[\\+\\-]?\\d+\\.*\\d*\', val, 1) #以表达式进行分割,1是从左到右 匹配第一个合适的。 类似 字符串的split new_str = \'%s%s%s\' % (before, value, after) #拼接 # print(new_str) arg[0] = new_str #更新列表的值 return compute_mul_div(arg) #递归处理 def comput(expression): # expression = "9-2*5/3+7/3*99/4*2998+10*568/14" #将传入的四则做成列表 这样修改函数形参则该列表也变化,因此不用return也行 inp = [expression,] # 处理乘除 方法 compute_mul_div(inp) # 处理加减 return compte_add_sub(inp) def excut(expression): kuohao=[] # 左括号 索引加入列表 if expression.find("(") == -1: #如果匹配不到左括号就直接交给计算四则的函数 ret = comput(expression) return ret for i in range(len(expression)): if "(" == expression[i]: # 循环字符串,遇到左括号加入空列表 kuohao.append(i) elif ")" == expression[i]: # 一旦遇到右括号,就跟上面左括号列表的最后一个元素还有遇到的这个右括号进行切片 ans_kuo = expression[kuohao[-1]+1:i] ret_num = comput(ans_kuo) expression = expression[0:kuohao[-1]]+str(ret_num)+expression[i+1:] print(expression) return excut(expression) # # \\(([\\+\\-\\*\\/]*\\d+\\.*\\d*){2,}\\) 是找 这一类 : 括号开始 接+ - * / 然后是数字1个或多个 小数点 数字0个或多个 类似-77.77 至少匹配2次 然后 括号结尾 : (-77.9*-88+99/3) # if not re.search(\'\\(([\\+\\-\\*\\/]*\\d+\\.*\\d*){2,}\\)\', expresiong): # final = comput(expresiong) #匹配不到了就交个这个计算四则的方法 # return final # jus = re.search(\'\\(([\\+\\-\\*\\/]*\\d+\\.*\\d*){2,}\\)\', expresiong).group() #取得括号表达式 (1-40/5*5+3-2*5/3) # #print(jus) # befor, nothing, after = re.split(\'\\(([\\+\\-\\*\\/]*\\d+\\.*\\d*){2,}\\)\', expresiong, 1) #以单层括号表达式分割 (1-40/5*5+3-2*5/3) 比如, 作为分隔符 但是只显示/3 这部分,所以先在上面取到表达式 # #print(nothing) # jus = jus[1:len(jus) - 1] #去除 分割表达式的括号 :1-40/5*5+3-2*5/3 # #print(\'222\', jus) # result = comput(jus) #交给四则运算的方法 # result = float(result) # #result = float(\'%0.7f\'%result) # result=str(result) # #print(result) # new_expression = "%s%s%s" % (befor, result, after) #四则计算完后拼接 # # print(new_expression) # return excut(new_expression) #将新的表达式返回给函数 ,递归处理 def main(): # a = \'1 - 2 * ((60-30 +(1-40/5*5+3-2*5/3) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2))\' default = \'1-2*(3+4)-6/3-6+7\' a = input("\\033[35;1m请输入表达式,只能包含小数点 四则运算符 小括号\\n表达式:\\033[0m") lx = re.sub("[\\d+\\.\\+\\-\\*\\/\\s*\\(\\)]","",a) if len(lx) != 0: print("\\033[31;1m表达式有其他特殊符号\\033[0m") return main() if "(" in a: if a.count("(") != a.count(")"): print("\\033[31;1m表达式括号个数不匹配\\033[0m") return main() a = default if len(a) == 0 else re.sub("\\s*", \'\', a) # 三元运算给a默认值,否则 给表达式去除空格 ret = excut(a) # 调用excut 方法 并将返回值给ret print("\\033[33;1m公式为:\\033[0m",a) print("\\033[35;1m结果为:\\033[0m",ret) if __name__ == \'__main__\': main()
version2
#!/usr/bin/env python # _*_ coding:utf-8 _*_ import re def compte_add_sub(inp): # inp = [\'-9-8.8++9--9\',] arg = inp[0] # 传入的只剩下 加减的字符串为列表 获取第一个值 #去除++ +- -- -+ if arg.find("+-") != -1 or arg.find("-+") != -1: arg = arg.replace("+-","-",len(arg)) arg = arg.replace("-+","-",len(arg)) elif arg.find("++") != -1 or arg.find("--") != -1: arg = arg.replace("++","+",len(arg)) arg = arg.replace("--","+",len(arg)) new_m = re.search(\'[\\-]*\\d+\\.*\\d*[\\-\\+]+\\d+\\.*\\d*\',arg) # 匹配 -9.9 + 9.9 或者 -9.9 - 9.9 if not new_m: #print(1766666,arg) return arg # 递归处理,当匹配不到上面的表达式就将表达式结果返回 即处理加减后的结果 else: brefor,after = re.split(\'[\\-]*\\d+\\.*\\d*[\\+\\-]+\\d+\\.*\\d*\',arg,1) #以匹配到的表达式为分隔符 分割 new_m=new_m.group() #定义成列表 将匹配到的表达式 if new_m.find("+") != -1: #如果匹配的是+号 new_m=new_m.split("+") #以+号分割 # print(new_m) zhi = float(new_m[0]) + float(new_m[1]) #计算加号 else: #减号的话 if new_m.startswith("-"): #如果匹配到的表达式以减号开头 #对应的序列元素第一个是空 new_m=new_m.split("-") #以减号分割 zhi = -(float(new_m[1]) + float(new_m[2])) #提出减号 内部相加即可 # print(zhi) else: #如果不以减号开头则 直接按分割收的序列 new_m=new_m.split("-") # print(new_m) zhi = float(new_m[0]) - float(new_m[1]) #zhi = float(\'%0.6f\'%zhi) #浮点数优化精度 #print(zhi) arg = brefor + str(zhi) +after #字符串类型进行拼接 # print(arg) inp = [arg,] #更改列表 # print(inp) return compte_add_sub(inp) #处理乘除 def compute_mul_div(arg): arg = arg[0] #print(arg) end =len(arg) ###########计算平方########## arg = re.sub("(//)","/",arg) #print(arg) while True: x = re.search("\\d+\\.*\\d*(\\*\\*)\\d+\\.*\\d*",arg) if x: expre = x.group() print(expre) x = x.group().split("**") ret = float(x[0]) ** float(x[-1]) if "e" in str(ret): ret=int(ret) #print(ret) arg = arg.replace(expre,str(ret),1) print(arg) else: #print("exit") break ###########计算平方########## # num = arg.count("*",0,end) +arg.count("/",0,end) li = re.findall(r"[*/]",arg) #匹配 * / 做到列表 #print(li) num = len(li) for i in range(num): #循环列表的下标 new = arg.split(li[i],1) #以乘除号为分隔符进行分割 la=re.findall("[\\+\\-\\/]?(\\d+\\.?\\d*)",new[0])[-1] #获取分隔符左侧字符串的最后一个数字,匹配浮点数 sta = re.findall("([\\+\\-\\/]?\\d+\\.?\\d*)",new[1])[0] #获取分隔符右侧字符串的第一一个数字,匹配浮点数 #print(la,sta) if li[i] == "*": #如果分隔符是* 计算乘 new_che = float(la) * float(sta) else: new_che = float(la) / float(sta) #print(new_che) # arg = re.sub(la+"*"+sta,new_che,new,1) arg = new[0][0:-len(la)] + str(new_che) +new[1][len(sta):] # 分割拼接 #print(arg) arg=[arg,] #print(3333333333,arg) return compte_add_sub(arg) def comput(expression): # expression = "9-2*5/3+7/3*99/4*2998+10*568/14" #将传入的四则做成列表 这样修改函数形参则该列表也变化,因此不用return也行 inp = [expression,] # 处理乘除 方法 n= compute_mul_div(inp) return n def以上是关于Python全栈--6.1-match-search-findall-group(s)的区别以及计算器实例的主要内容,如果未能解决你的问题,请参考以下文章