失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Python学习——正则表达式与re模块实现字符串计算器

Python学习——正则表达式与re模块实现字符串计算器

时间:2022-04-03 15:26:38

相关推荐

Python学习——正则表达式与re模块实现字符串计算器

学习了python的正则表达式后,一片懵逼,不知道干啥用的,也不知道咋用,只能放一些实例和正则表达式的规则以备后续查阅,希望在经过长时间的训练和使用后能对正则表达式有一个深刻的理解。什么是正则表达式呢?借用林海峰老师的话说就是:描述一类事物的规则。在Python中就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法,并通过 re 模块实现。

先介绍正则表示一些常用的匹配模式,以及结合re模块的使用方法,然后写一个基于正则表达式、字符串的计算器

正则表达式常用的匹配模式如下表:

下面就来详细一个分析吧:

以下举例部分摘自林海峰博客

/linhaifeng/articles/6384466.html#_label13

import re#\w与\Wprint(re.findall('\w','hello egon 123')) #['h', 'e', 'l', 'l', 'o', 'e', 'g', 'o', 'n', '1', '2', '3']print(re.findall('\W','hello egon 123')) #[' ', ' ']#\s与\Sprint(re.findall('\s','hello egon 123')) #[' ', ' ', ' ', ' ']print(re.findall('\S','hello egon 123')) #['h', 'e', 'l', 'l', 'o', 'e', 'g', 'o', 'n', '1', '2', '3']#\n \t都是空,都可以被\s匹配print(re.findall('\s','hello \n egon \t 123')) #[' ', '\n', ' ', ' ', '\t', ' ']#\n与\tprint(re.findall(r'\n','hello egon \n123')) #['\n']print(re.findall(r'\t','hello egon\t123')) #['\n']#\d与\Dprint(re.findall('\d','hello egon 123')) #['1', '2', '3']print(re.findall('\D','hello egon 123')) #['h', 'e', 'l', 'l', 'o', ' ', 'e', 'g', 'o', 'n', ' ']#\A与\Zprint(re.findall('\Ahe','hello egon 123')) #['he'],\A==>^print(re.findall('123\Z','hello egon 123')) #['he'],\Z==>$#^与$print(re.findall('^h','hello egon 123')) #['h']print(re.findall('3$','hello egon 123')) #['3']# 重复匹配:| . | * | ? | .* | .*? | + | {n,m} |#.print(re.findall('a.b','a1b')) #['a1b']print(re.findall('a.b','a1b a*b a b aaab')) #['a1b', 'a*b', 'a b', 'aab']print(re.findall('a.b','a\nb')) #[]print(re.findall('a.b','a\nb',re.S)) #['a\nb']print(re.findall('a.b','a\nb',re.DOTALL)) #['a\nb']同上一条意思一样#*print(re.findall('ab*','bbbbbbb')) #[]print(re.findall('ab*','a')) #['a']print(re.findall('ab*','abbbb')) #['abbbb']#?print(re.findall('ab?','a')) #['a']print(re.findall('ab?','abbb')) #['ab']#匹配所有包含小数在内的数字print(re.findall('\d+\.?\d*',"asdfasdf123as1.13dfa12adsf1asdf3")) #['123', '1.13', '12', '1', '3']#.*默认为贪婪匹配print(re.findall('a.*b','a1b22222222b')) #['a1b22222222b']#.*?为非贪婪匹配:推荐使用print(re.findall('a.*?b','a1b22222222b')) #['a1b']#+print(re.findall('ab+','a')) #[]print(re.findall('ab+','abbb')) #['abbb']#{n,m}print(re.findall('ab{2}','abbb')) #['abb']print(re.findall('ab{2,4}','abbb')) #['abb']print(re.findall('ab{1,}','abbb')) #'ab{1,}' ===> 'ab+'print(re.findall('ab{0,}','abbb')) #'ab{0,}' ===> 'ab*'#[]print(re.findall('a[1*-]b','a1b a*b a-b')) #[]内的都为普通字符了,且如果-没有被转意的话,应该放到[]的开头或结尾print(re.findall('a[^1*-]b','a1b a*b a-b a=b')) #[]内的^代表的意思是取反,所以结果为['a=b']print(re.findall('a[0-9]b','a1b a*b a-b a=b')) #[]内的^代表的意思是取反,所以结果为['a=b']print(re.findall('a[a-z]b','a1b a*b a-b a=b aeb')) #[]内的^代表的意思是取反,所以结果为['a=b']print(re.findall('a[a-zA-Z]b','a1b a*b a-b a=b aeb aEb')) #[]内的^代表的意思是取反,所以结果为['a=b']#\# print(re.findall('a\\c','a\c')) #对于正则来说a\\c确实可以匹配到a\c,但是在python解释器读取a\\c时,会发生转义,然后交给re去执行,所以抛出异常print(re.findall(r'a\\c','a\c')) #r代表告诉解释器使用rawstring,即原生字符串,把我们正则内的所有符号都当普通字符处理,不要转义print(re.findall('a\\\\c','a\c')) #同上面的意思一样,和上面的结果一样都是['a\\c']#():分组print(re.findall('ab+','ababab123')) #['ab', 'ab', 'ab']print(re.findall('(ab)+123','ababab123')) #['ab'],匹配到末尾的ab123中的abprint(re.findall('(?:ab)+123','ababab123')) #findall的结果不是匹配的全部内容,而是组内的内容,?:可以让结果为匹配的全部内容print(re.findall('href="(.*?)"','<a href="">点击</a>'))#['']print(re.findall('href="(?:.*?)"','<a href="">点击</a>'))#['href=""']#|print(re.findall('compan(?:y|ies)','Too many companies have gone bankrupt, and the next one is my company'))

re模块函数介绍

match(pattern, string, flags=0)

这个方法只从string 的头部匹配,匹配失败返回None,匹配成功返回Match object,注意是一个对象,可以通过返回的对象调用其内部方法获得匹配的信息。match对象的方法:

1.string:方法返回被匹配的字符串

2.start:返回指定的组在字符串中开始匹配的位置,组取值默认值为0

3.end:返回指定的组在字符串中开始匹配的位置,组取值默认值为0

4.pos,endpos:返回起始和终止匹配位置

5.group:返回指定组的匹配字符串

6.groupdict:返回有别名的组的别名为键、以该组截获的子串为值的字典,没有别名的组不包含在内。

7.lastgroup:返回最后一个被捕获的分组的别名。如果这个分组没有别名或者没有被捕获的分组,将为None。

8.lastindex:返回最后一个分组在文本中的索引

9.span:返回(start(group), end(group)),即该组的起始和终止位置

10.expand:可以实现分组之间顺序的调整

fullmatch(pattern, string, flags=0)

fullmatch()函数或方法就相当于给match()函数或方法的pattern或string参数加上行首边界元字符'^'和行尾边界元字符'$';即对整个字符串进行匹配

search(pattern, string, flags=0)

这个方法对整个字符串进行搜索,并返回第一个匹配的Match object对象,然后立即返回,若匹配失败返回None。返回的Match objec使用方法同上

findall(pattern, string, flags=0)

此方法以列表的形式返回能匹配的所有子串

sub(pattern, repl, string, count=0, flags=0)

subn(pattern, repl, string, count=0, flags=0)

sub函数返回的是被替换后的字符串,如果字符串中没有与正则表达式相匹配的内容,则返回原始字符串;subn函数除了返回被替换后的字符串,还会返回一个替换次数,它们是以元组的形式返回。

附加一个不错的关于re模块使用的博客:/yyds/p/6953348.html

下面的代码是使用re模块完成一个字符串计算器:

# expression='1-2*((60+2*(-3-40.0/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))''''思路:1、找出表达式中最深的(),若表达式内无(),则进入步骤 52、找出最深的()范围内乘法或者除法进入步骤 3,若表达式内没有乘法或者除法,则进入步骤 43、计算乘法或者除法,然后将结果拼接回表达式,回到步骤 24、计算表达式内剩余的加法或者减法,然后回到步骤 15、计算没有()的表达式,先计算乘法或者除法,然后计算加法或者减法,最后返回计算结果'''import sysimport redef get_expression():while True:iput_expression = input("请输入你要计算的表达式[按下q:退出]:").strip()if iput_expression == 'q': # 退出计算breakelif len(iput_expression) == 0:continueelse:iput_expression = re.sub('\s*', '', iput_expression) # 去除空格return iput_expressiondef caculate_mul_div(expression):result = re.search(r'\d+\.?\d*[\*\/]+[\+\-]?\d+\.?\d*', expression)if not result:return expressionresult = re.search(r'\d+\.?\d*[\*\/]+[\+\-]?\d+\.?\d*', expression).group()if len(result.split('*')) > 1:left, right = result.split('*')value = float(left) * float(right)else:left, right = result.split('/')if float(right) == 0:sys.exit("表达式中有除数为 0 存在,无法完成计算")else:value = float(left) / float(right)#value = int(value)print("计算前表达式为:%s"%expression)print("计算:%s = %s"%(result, value))left, right = re.split(r'\d+\.?\d*[\*\/]+[\+\-]?\d+\.?\d*', expression, 1)caculate_expression = "%s%s%s"%(left, value, right)print("计算后表达式为:%s"%caculate_expression)return caculate_mul_div(caculate_expression)def calulate_add_sub(expression):expression = expression.replace('+-', '-')expression = expression.replace('--', '+')expression = expression.replace('-+', '-')expression = expression.replace('++', '+')print("+-符号去重后的表达式为:%s"%expression)result= re.search(r'\d+\.?\d*[\+\-]{1}\d+\.?\d*', expression)if not result:return expressionresult = re.search(r'[\-]?\d+\.?\d*[\+\-]{1}\d+\.?\d*', expression).group()if len(result.split('+')) > 1:left, right = result.split('+')value = float(left) + float(right)elif result.startswith('-'):left, mid, right = result.split('-')value = -float(mid) - float(right)else:left, right = result.split('-')value = float(left) - float(right)print("计算前表达式为:%s" % expression)print("计算:%s = %s" % (result, value))left, right = re.split(r'[\-]?\d+\.?\d*[\+\-]{1}\d+\.?\d*', expression, 1)caculate_expression = "%s%s%s" % (left, value, right)print("计算后表达式为:%s" % caculate_expression)return calulate_add_sub(caculate_expression)def caculate(expression):if not re.search(r'\(([^()]+)\)',expression): #判断表达式中是否还有小括号,无,则进行最后的计算并返回计算结果result = caculate_mul_div(expression)result = calulate_add_sub(result)return resultmax_deep_expression = re.search('\(([^()]+)\)',expression).group() #找出层次最深的()max_deep_expression = max_deep_expression.strip('[\(\)]')result = caculate_mul_div(max_deep_expression)result = calulate_add_sub(result)left, max_deep_str, right = re.split(r'\(([^()]+)\)', expression, 1)expression = '%s%s%s'%(left, result, right)return caculate(expression)if __name__ == '__main__':try:expression = get_expression()print("expression is:", expression)eval_reslut = eval(expression)caculate_result = caculate(expression)print("eval计算结果为:", eval_reslut)print("caculate计算结果为:", caculate_result)if float(eval_reslut) != float(caculate_result):print("eval计算结果与caculate计算结果不一致")except(SyntaxError, ValueError,TypeError):print("输入表达式有误,请重新输入!")

以上计算器的实现大家可以验证一下,有不对之处请指正。

如果觉得《Python学习——正则表达式与re模块实现字符串计算器》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。