小白学习Python之路---re模块学

2020-01-16 12:21:19 浏览数 (1)

本节大纲:

  1.正则表达式

  2.re模块的学习

  3.速记理解技巧

  4.挑战练习--开发一个简单的python计算器

  5.心得总结

  6.学习建议

正则表达式:

正则表达式,又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。

 正则表达式是对字符串(包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为“元字符”))操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。正则表达式是一种文本模式,该模式描述在搜索文本时要匹配的一个或多个字符串。

  特点:    

    1. 灵活性、逻辑性和功能性非常强。

    2. 可以迅速地用极简单的方式达到字符串的复杂控制。

    3. 对于刚接触的人来说,比较晦涩难懂。

re模块

re模块是Python提供对正则表达式支持的一个模块,里面的常用函数为:

代码语言:javascript复制
1 re.match 从头开始匹配
2 re.search 匹配包含
3 re.findall 把所有匹配到的字符放到以列表中的元素返回
4 re.splitall 以匹配到的字符当做列表分隔符
5 re.sub      匹配字符并替换re.sub的参数(表达式规则,新字符串,旧字符串,替换数量为1(count=1))

   常用的正则表达式符号,一般的,基本够用了

代码语言:javascript复制
 1 '.'     默认匹配除n之外的任意一个字符,若指定flag DOTALL,则匹配任意字符,包括换行
 2 '^'     匹配输入字行首,若指定flags MULTILINE,这种也可以匹配上(r"^a","nabcneee",flags=re.MULTILINE)
 3 '$'     匹配输入行尾,或e.search("foo$","bfoonsdfsf",flags=re.MULTILINE).group()也可以
 4 '*'     匹配前面的子表达式任意次,re.findall("ab*","cabb3abcbbac")  结果为['abb', 'ab', 'a']
 5 ' '     匹配前面的子表达式一次或多次(大于等于1次),re.findall("ab ","ab cd abb bba") 结果['ab', 'abb']
 6 '?'     匹配前面的子表达式零次或一次
 7 '{m}'   匹配前一个字符m次
 8 '{n,m}' 匹配前一个字符n到m次,re.findall("ab{1,3}","abb abc abbcbbb") 结果'abb', 'ab', 'abb']
 9 '|'     匹配|左或|右的字符,re.search("abc|ABC","ABCBabcCD").group() 结果'ABC'
10 '(...)' 分组匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group() 结果 abcabca456c
11  
12  
13 'A'    只从字符开头匹配,re.search("Aabc","alexabc") 是匹配不到的
14 'Z'    匹配字符结尾,同$
15 'd'    匹配数字0-9
16 'D'    匹配非数字
17 'w'    匹配[A-Za-z0-9]
18 'W'    匹配非[A-Za-z0-9]
19 's'    匹配空白字符、t、n、r , re.search("s ","abtc1n3").group() 结果 't'
20  
21 '(?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'}

 速记理解技巧

代码语言:javascript复制
1 .
2 []
3 ^
4 $

   上面四个字符是所有语言都支持的正则表达式,所以这四个是基础的正则表达式。正则难理解因为里面有一个等价的概念,这个概念大大增加了理解难度,让很多初学者看起来会懵,如果把等价都恢复成原始写法,自己书写正则就超级简单了,就像说话一样去写你的正则了:

等价:

代码语言:javascript复制
1 等价是等同于的意思,表示同样的功能,用不同符号来书写。?,*, ,d,w 都是等价字符
2   ?等价于匹配长度{0,1}
3   *等价于匹配长度{0,} 
4    等价于匹配长度{1,}
5   d等价于[0-9]
6   D等价于[^0-9]
7   w等价于[A-Za-z_0-9]
8   W等价于[^A-Za-z_0-9]。

常用运算符与表达式:

代码语言:javascript复制
 1   ^ 开始
 2   () 域段
 3   [] 包含,默认是一个字符长度
 4   [^] 不包含,默认是一个字符长度
 5   {n,m} 匹配长度 
 6   . 任何单个字符(. 字符点)
 7   | 或
 8    转义
 9   $ 结尾
10   [A-Z] 26个大写字母
11   [a-z] 26个小写字母
12   [0-9] 0至9数字
13   [A-Za-z0-9] 26个大写字母、26个小写字母和0至9数字 

分割语法:   [A,H,T,W] 包含A或H或T或W字母   [a,h,t,w] 包含a或h或t或w字母   [0,3,6,8] 包含0或3或6或8数字

语法与释义:   基础语法 "^([]{})([]{})([]{})$"   正则字符串 = "开始([包含内容]{长度})([包含内容]{长度})([包含内容]{长度})结束"    ?,*, ,d,w 这些都是简写的,完全可以用[]和{}代替,在(?:)(?=)(?!)(?<=)(?<!)(?i)(*?)( ?)这种特殊组合情况下除外。   初学者可以忽略?,*, ,d,w一些简写标示符,学会了基础使用再按表自己去等价替换

 一些常用的正则表达式例子(摘自百度百科)

代码语言:javascript复制
 1 1.验证用户名和密码:("^[a-zA-Z]w{5,15}$")正确格式:"[A-Z][a-z]_[0-9]"组成,并且第一个字必须为字母6~16位;
 2 2.验证电话号码:("^(d{3,4}-)d{7,8}$")正确格式:xxx/xxxx-xxxxxxx/xxxxxxxx;
 3 3.验证手机号码:"^1[3|4|5|7|8][0-9]{9}$";
 4 4.验证身份证号(15位):"d{14}[[0-9],0-9xX]",(18位):"d{17}(d|X|x)";
 5 5.验证Email地址:("^w ([- .]w )*@w ([-.]w )*.w ([-.]w )*$");
 6 6.只能输入由数字和26个英文字母组成的字符串:("^[A-Za-z0-9] $");
 7 7.整数或者小数:^[0-9] ([.][0-9] ){0,1}$
 8 8.只能输入数字:"^[0-9]*$"。
 9 9.只能输入n位的数字:"^d{n}$"。
10 10.只能输入至少n位的数字:"^d{n,}$"。
11 11.只能输入m~n位的数字:"^d{m,n}$"。
12 12.只能输入零和非零开头的数字:"^(0|[1-9][0-9]*)$"。
13 13.只能输入有两位小数的正实数:"^[0-9] (.[0-9]{2})?$"。
14 14.只能输入有1~3位小数的正实数:"^[0-9] (.[0-9]{1,3})?$"。
15 15.只能输入非零的正整数:"^ ?[1-9][0-9]*$"。
16 16.只能输入非零的负整数:"^-[1-9][0-9]*$"。
17 17.只能输入长度为3的字符:"^.{3}$"。
18 18.只能输入由26个英文字母组成的字符串:"^[A-Za-z] $"。
19 19.只能输入由26个大写英文字母组成的字符串:"^[A-Z] $"。
20 20.只能输入由26个小写英文字母组成的字符串:"^[a-z] $"。
21 21.验证是否含有^%&',;=?$"等字符:"[%&',;=?$\^] "。
22 22.只能输入汉字:"^[u4e00-u9fa5]{0,}$"。
23 23.验证URL:"^http://([w-] .) [w-] (/[w-./?%&=]*)?$"。
24 24.验证一年的12个月:"^(0?[1-9]|1[0-2])$"正确格式为:"01"~"09"和"10"~"12"。
25 25.验证一个月的31天:"^((0?[1-9])|((1|2)[0-9])|30|31)$"正确格式为;"01"~"09"、"10"~"29"和“30”~“31”。
26 26.获取日期正则表达式:\d{4}[年|-|.]d{1-12}[月|-|.]d{1-31}日?
27 评注:可用来匹配大多数年月日信息。
28 27.匹配双字节字符(包括汉字在内):[^x00-xff]
29 评注:可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)
30 28.匹配空白行的正则表达式:ns*r
31 评注:可以用来删除空白行
32 29.匹配HTML标记的正则表达式:<(S*?)[^>]*>.*?</>|<.*? />
33 评注:网上流传的版本太糟糕,上面这个也仅仅能匹配部分,对于复杂的嵌套标记依旧无能为力
34 30.匹配首尾空白字符的正则表达式:^s*|s*$
35 评注:可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式
36 31.匹配网址URL的正则表达式:[a-zA-z] ://[^s]*
37 评注:网上流传的版本功能很有限,上面这个基本可以满足需求
38 32.匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
39 评注:表单验证时很实用
40 33.匹配腾讯QQ号:[1-9][0-9]{4,}
41 评注:腾讯QQ号从10 000 开始
42 34.匹配中国邮政编码:[1-9]\d{5}(?!d)
43 评注:中国邮政编码为6位数字
44 35.匹配ip地址:([1-9]{1,3}.){3}[1-9]。
45 评注:提取ip地址时有用
46 36.匹配MAC地址:([A-Fa-f0-9]{2}:){5}[A-Fa-f0-9]

View Code

关于模块的挑战练习

需求:

代码语言:javascript复制
开发一个简单的python计算器

    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等类似功能偷懒实现),
    运算后得出结果,结果必须与真实的计算器所得出的结果一致

tips:
    
    re.search(r'([^()] )',s).group()

    '(-40/5)'

我的代码

代码语言:javascript复制
  1 #!/usr/bin/env python
  2 # -*- coding: utf-8 -*-
  3 # This is Jay's work!!
  4 # 2019年4月27日14:45:59
  5 
  6 """
  7 心得:
  8     1.一个函数,就应该只实现一个功能
  9     2.[^f]是匹配除中括号里面f的所有字符 ^f是匹配以f开头的字符 [^f] 是匹配除了f中的所有字符
 10     3.re.sub的参数(表达式规则,想替换成啥,被替换的字符串,替换数量)
 11     4.注意科学计数法,一般出现在除法的身上
 12     5.算式前面的负号是一个难受的点
 13     6.乘法中的负负得正也要注意
 14     7.先算乘除,后算加减,但是遇到乘除/加减同级,必须先从左到右依次进行计算
 15     8.re.complie能让程序看起来更简洁,而且运行速度更快
 16 过程:
 17     去掉算式中的空格-->
 18     找到最底层括号的一对算式(-40/5),传给count函数-->
 19     count函数将括号里面的算式进行加减乘除运算,将最后结果(-8.0)返回给变量back-->
 20     将(-8.0)里面的内容提取出来成'-8.0',然后就替换原来算式中的(-40/5)-->
 21     循环上述过程-->
 22     到最后没有括号的时候,就直接用count函数算出结果,替换原来的式子,成为结果
 23     
 24 """
 25 import re
 26 
 27 
 28 def multiplication(m):
 29     """计算乘法"""
 30     # 将算式分开
 31     res = m.split('*')
 32     answer = float(res[0]) * float(res[1])
 33 
 34     if float(res[0]) < 0 and float(res[1]) < 0:  # 负负得正
 35         answer = ' '   str(answer)
 36     return str(answer)
 37 
 38 
 39 def division(m):
 40     """计算除法"""
 41     # 将算式分开
 42     res = m.split('/')
 43     answer = float(res[0]) / float(res[1])
 44     if 'e' in str(answer):  # 除出来的结果如果是科学计数法
 45         answer = as_num(answer)
 46     return str(answer)
 47 
 48 
 49 def addition(m):
 50     """计算加法"""
 51     # 将算式分开
 52     res = m.split(' ')
 53     answer = float(res[0])   float(res[1])
 54     return str(answer)
 55 
 56 
 57 def subtraction(m):
 58     """计算减法"""
 59     # 将算式分开
 60     res = m.split('-')
 61     answer = float(res[0]) - float(res[1])
 62     return str(answer)
 63 
 64 
 65 def as_num(x):
 66     """这是一个函数,将科学计数法的数据转换成浮点数的功能"""
 67     y = '{:.20f}'.format(x)  # 20f表示保留20位小数点的float型
 68     return (y)
 69 
 70 
 71 def count(formula):
 72     """一个能简单算出加减乘除的函数"""
 73 
 74     # 下面是乘除法循环
 75     while '*' or '/' in formula:
 76         # 预先将正则表达式的字符串形式编译为实例,这样用着实例的方法,可以加快程序的运行
 77         # 正则表达式:
 78         #           '-?[0-9] .?[0-9]*' 一个负号或者没有 数字 小数点一个或者没有 数字
 79         #           '[*|/]' 匹配乘号'*'或者除号'/' 乘号除号都需要转义
 80         #           '-?[0-9] .?[0-9]*' 一个负号或者没有 数字 小数点一个或者没有 数字
 81 
 82         pattern = re.compile('-?[0-9] .?[0-9]*[*|/]-?[0-9] .?[0-9]*')
 83         res = pattern.search(formula)
 84         try:  # 若找不到,会有none异常错误,所以在这里抓住一下
 85             if '*' in res.group():
 86                 back = multiplication(res.group())
 87             elif '/' in res.group():
 88                 back = division(res.group())
 89         except AttributeError:
 90             # print('已经没有算式了')
 91             break
 92         # 用接收回来的结果替换原来的结果
 93         formula = pattern.sub(back, formula, count=1)
 94 
 95     # 接下来是加减法循环
 96     while ' ' or '-' in formula:
 97         # 正则表达式:
 98         #           '-?[0-9] .?[0-9]*' 一个负号或者没有 数字 小数点一个或者没有 数字
 99         #           '[ |/]' 匹配加好' '或者减号'-',加好需要转义,减号不需要
100         #           '-?[0-9] .?[0-9]*' 一个负号或者没有 数字 小数点一个或者没有 数字
101 
102         pattern = re.compile('-?[0-9] .?[0-9]*[ |-]-?[0-9] .?[0-9]*')
103         res = pattern.search(formula)
104         try:  # 若找不到,会有none异常错误,所以在这里抓住一下
105             # print(res.group())  # 最后还会有一个none
106             if ' ' in res.group():
107                 back = addition(res.group())
108             elif '-' in res.group():
109                 back = subtraction(res.group())
110         except AttributeError:
111             # print("已经没有算式了")
112             break
113         formula = pattern.sub(back, formula, count=1)
114 
115     # 将计算完的算式,返回给调用函数
116     return formula
117 
118 
119 def symbol_conversion(formula):
120     """这是一个函数,处理负号与正号"""
121     formula = re.sub(' -', '-', formula)  # 数字前面是' -'
122     formula = formula.replace('--', ' ')   # 数字前面是'--'
123 
124     return formula
125 
126 
127 def find(formula):
128     """找到最底层的括号,会成为一个列表,将最底层同级的括号作为一个元素存储"""
129     # 正则表达式:
130     #           '([^()] )' 匹配最底层括号
131     #            (  ) 两个转义括号  [^()] 里面没有括号
132     brackets_pattern = re.compile('([^()] )')
133 
134     # 正则表达式:
135     #           '[^((] (?=[))])' 匹配括号里面的内容
136     brackets_content = re.compile('[^((] (?=[))])')
137 
138     res = brackets_pattern.findall(formula)
139     for i in range(len(res)):
140         back = count(res[i])  # 替换算式中的结果,并去掉括号,eg:(-40/5)-->(-8.0)
141         # print(back)
142         back = brackets_content.findall(back)  # 将括号里面的内容取出来
143         # print(back[0])
144         formula = formula.replace(res[i], str(back[0]))  # 替换算式中的结果,并去掉括号,eg:(-8.0)-->-8.0
145     formula = symbol_conversion(formula)
146     print('一轮结果的算式', formula)
147     return formula
148 
149 
150 if __name__ == '__main__':
151 
152     formula = "1 - 2 * ( (60-30  (-40/5) * (9-2*5/3   7 /3*99/4*2998  10 * 568/14 )) - (-4*3)/ (16-3*2) )"
153     # formula = input("请输入算式")
154     # 先去掉空格
155     formula = formula.replace(' ', '')
156     print('开始运算前算式', formula)
157     while '(' in formula:
158         # 有括号就进行括号的运算
159         formula = find(formula)
160     else:
161         # 没有括号就直接算
162         formula = count(formula)
163 
164     print("最后的最后的最后的算式为", formula)

View Code

心得总结

  这个作业前前后后做了三天,当时刚刚看完re模块的学习视频,觉得大多数功能还是了解的,然后就没尝试去做,觉得应该不难。但是视频里面Alex老师说这个作业挺有挑战性的,如果做了两天都没写出来就不必要写了。现在写完,发现还真是有点挑战性,我说说我写的大致过程吧。

  刚开始,看着需求在发呆,想着如何把底层括号提取出来(当是没看到博客下面有个提示,提取底层括号的正则表达式),就自己硬着头皮在那里写,我早上九点开始写,憋了三个小时,到中午,一点东西都没写出来,真的,是完全没有思路,就连最基本的表达式符号也不知道是干嘛的( . * ? ),然后我又去其他博客上面看人家写的,也看不懂。只能硬着头皮,回去再重刷一遍视频,这次我看视频看得无比认真,也没有加快播放速度。

  第二次看完视频,就真的是理解了大概的作用了,然后也看到了博客下面的提示,就可以开始写了,就拿上面的例子算式来写吧,我刚开始提取出来的是(-40/5),觉得这个没难度,因为提取出来的是一个列表,我一个一个的打印出来,看看效果,最终决定将这个(9-2*5/3 7 /3*99/4*2998 10 * 568/14 )) 式子作为切入点,因为里面涵盖了加减乘除。我在写的时候陷进了一个超大的错误误区,我以为先算乘除,可以先算完所有乘法,再算除法,结果是真的天真了,所以在代码的开头我就写上了,同级乘除,必须从左到右。本来按照我的想法,还是挺简单就实现了功能的,一开始先提取所有*号两边的数字,第一次就提取到了(2*5)返回10,其实这样也是错的,数字前面那个负号也是需要提取的,不然返回结果肯定又出差错,然后到算除法的时候,更难受,返回了一个科学计数法的数字,然后下面的正则表达式就报错了,当时我想的是再写了一个正则表达式去提取科学计数法的,后来突然灵光一闪,是不是可以将科学计数法转换为一般形式呢,然后就去疯狂的百度,挺好的,因为当时总算找到了。乘除算完,并替换回原式,我以为接下来的算加减就简单了,就打印一下结果,当时完全没预料到结果返回的是( -)或者(--),这个没预料到,然后就又写了一个函数去处理这个结果,而且我在每次替换原式的时候都调用这个函数。

  主要就是这几个问题吧,(同级运算,科学计数法,负负得正,负号在数字前面得带着一起运算)在开始写程序的时候,完全没想到的问题,在写的时候就慢慢的露了出来,期间我重构过很多次计算的那个函数,花费了不少精力,而且正则表达式的写,除了找底层括号那个,其他都是自己写出来的。

  对于我贴出来的这个代码,我已经将必要的解释都写了上去,那个代码是最终版的,写完的时候我回头看的时候也看不懂(哈哈),但是那个确实是简洁了,我在下面也贴出我未整理的代码,让你们看看对比,挺乱的,但是那个未整理的代码,我一眼看去就知道逻辑思维,瞬间就能懂得。文章最后是Alex老师的代码。

学习建议

  1.不要总是“我觉得”,你看上面的文字,我是不是用了许多‘我觉得’,这只是为了给你看看当时我多傻,真的,不要太理所当然,写代码是这样,做人也是这样。

  2.在开始写代码之间,最好还是多多思考一下整个的算法流程,就像这个作业,先理清功能:找底层括号-->算括号里面表达式-->结果替换原式-->循环如此

  3.看到程序报错不要慌张,这个是好事,多看一个错误,多一分成长

  4.多多print看程序运行的结果,思考结果的产生

  5.遇到不懂的知识,多多百度谷歌,做好笔记

  6.就算有答案,不到万不得已都别去看,锻炼自己的思维,我在写这个程序,过程中,没看过一眼答案,当写不出正则表达式的时候,有时候我真的很想去看一看答案,但是我每次都忍住了

  7.看懂别人代码是有困难的,我写完之后,花了几分钟去看了看Alex的博客答案,也还是没看懂,但是我还是会去看,学一学别人的逻辑思维

  8.写程序尽量不要停,挑一个安安静静的时间,关掉手机,开开心心地写,我断断续续写了三天,每次从新回到程序的过程中,都非常慢

  9.真的写不出程序的时候,歇一歇,听首歌,回去看看基本语法,会有作用的

  10.不要熬夜一直写,伤身(虽然我有一次写到两点)

我自己能看懂的代码

代码语言:javascript复制
  1 #!/usr/bin/env python
  2 
  3 # -*- coding: utf-8 -*-
  4 
  5 # This is Jay's work!!
  6 """
  7     1.一个函数,就应该只实现一个功能
  8     2.[^f]是匹配除中括号里面f的所有字符 ^f是匹配以f开头的字符 [^f] 是匹配除了f中的所有字符
  9     3.re.sub的参数(表达式规则,想替换成啥,被替换的字符串,替换数量)
 10     4.注意科学计数法
 11     5.算式前面的负号是一个难受的点
 12     6.乘法中的负负得正也要注意
 13     7.先算乘除,后算加减,但是遇到乘除/加减同级,必须先从左到右依次进行计算
 14 """
 15 import re,string
 16 
 17 def multiplication(m):
 18     """计算乘法"""
 19     res = m.split('*')
 20     # print(res)
 21     answer = float(res[0])*float(res[1])
 22     if float(res[0])<0 and float(res[1])<0:
 23         answer =' '   str(answer)
 24     return answer
 25 def division(m):
 26     """计算除法"""
 27     res = m.split('/')
 28     print(float(res[0]))
 29     print(float(res[1]))
 30     answer = float(res[0])/float(res[1])
 31     if 'e' in str(answer):
 32         answer = as_num(answer)
 33     return answer
 34 def addition(m):
 35     """计算加法"""
 36     res = m.split(' ')
 37     answer = float(res[0]) float(res[1])
 38     return answer
 39 
 40 def subtraction(m):
 41     """计算减法"""
 42     res = m.split('-')
 43     answer = float(res[0]) - float(res[1])
 44     return answer
 45 
 46 def find_brackets(m):
 47     """找到最底层的括号"""
 48 
 49 
 50 def as_num(x):
 51     y='{:.20f}'.format(x) # 20f表示保留20位小数点的float型
 52     return(y)
 53 
 54 
 55 def count(formula):
 56     """先做一个能简单算出加减乘除的函数先"""
 57     print("接收到的算式",formula)
 58     # #先判断乘法的
 59     # print("*"*50)
 60     # if '*' in formula:
 61     #     res = re.findall('-?d .?d**-?d .?d*',formula)
 62     #     print("现在的res>>>>>>",res)
 63     #     for i in range(len(res)):
 64     #         # print("变化之前的i",res[i])
 65     #         back = multiplication(res[i])   #算出所有乘法两边的值,然后传回来将本来传过去的那个式子给替换掉
 66     #         # print("变化之后的i",back)
 67     #         res[i]= back
 68     #     # print("not the formula---",formula)
 69     #     print("现在的res>>>>>>",res)
 70     #     for i in range(len(res)):
 71     #         # print(res[i])
 72     #         formula = re.sub('-?d .?d**-?d .?d*',str(res[i]),formula,count=1)    #参数(表达式规则,想替换成啥,被替换的字符串,替换数量)
 73     #
 74     #     print("look here man..****..",formula)
 75     #
 76     # #再判断除法
 77     # print('/'*50)
 78     # while '/' in formula:
 79     #     res = re.search('-?[0-9] .?[0-9]*/[0-9] .?[0-9]*',formula)
 80     #     print(res.group())
 81     #     back = division(res.group())
 82     #     print(back)
 83     #     formula = re.sub('-?[0-9] .?[0-9]*/[0-9] .?[0-9]*',str(back),formula,count=1)
 84     #     print("》》》》》》》》》",formula)
 85     #
 86     #
 87     # print(' '*50)
 88     # # if '-' in formula:
 89     # #     res = re.search('-[0-9] .?[0-9]*',formula)
 90     # #     print(res)
 91     # print(formula)
 92     # 来,先判断乘除
 93     print('/*' * 50)
 94     while '*' or '/' in formula:
 95         print('现在进入了乘除法的循环')
 96         print(formula)
 97         res = re.search('-?[0-9] .?[0-9]*[*|/]-?[0-9] .?[0-9]*', formula)
 98         print(res)
 99         try:
100             print(res.group())
101             if '*' in res.group():
102                 back = multiplication(res.group())
103             elif '/' in res.group():
104                 back = division(res.group())
105         except AttributeError:
106             print('已经没有算式了')
107             break
108         print("乘除法接收的结果", back)
109 
110         formula = re.sub('-?[0-9] .?[0-9]*[*|/]-?[0-9] .?[0-9]*', str(back), formula, count=1)
111     while ' ' or '-' in formula:
112         print('现在进入了加减法的循环')
113         res = re.search('-?[0-9] .?[0-9]*[ |-]-?[0-9] .?[0-9]*', formula)
114         print(res)
115         try:
116             print(res.group())      #最后还会有一个none
117             if ' ' in res.group():
118                 back = addition(res.group())
119             elif '-' in res.group():
120                 back = subtraction(res.group())
121         except AttributeError:
122             print("已经没有算式了")
123             break
124         print(back)
125         formula = re.sub('-?[0-9] .?[0-9]*[ |-]-?[0-9] .?[0-9]*', str(back), formula, count=1)
126         print("现在的算式为》》》》》》》》》", formula)
127     else:
128         print("have done")
129 
130     print('&'*50,formula)
131     new_formula = formula
132     return new_formula
133     # while '-' in formula:
134     #     res = re.search('[0-9] .?[0-9]*-[0-9] .?[0-9]*', formula)
135     #     print(res.group())
136     #     back = subtraction(res.group())
137     #     print(back)
138     #     formula = re.sub('[0-9] .?[0-9]*-[0-9] .?[0-9]*', str(back), formula, count=1)
139     #     print("》》》》》》》》》", formula)
140 
141     # if '/' in formula:
142     #     res = re.findall('[0-9] .?[0-9]*/[0-9] .?[0-9]*',formula)
143     #     print(res)
144     #     for i in range(len(res)):
145     #         back = division(res[i])
146     #         res[i]=back
147     #     print("现在res又变成了",res)
148     #     for i in range(len(res)):
149     #         print(re.search('[0-9] .?[0-9]*/[0-9] .?[0-9]*',formula))
150     #         # formula = re.sub('[0-9]?.?[0-9] /d ',str(res[i]),formula,count=1)  #还有一个"/"没有匹配上
151     #         formula = re.sub('[0-9] .?[0-9]*/[0-9] .?[0-9]*',str(res[i]),formula,count=1)
152     #     print("你再看》》》》》",formula)
153     #
154     # print('/'*50)
155     # if '/' in formula:
156     #     res = re.findall('[0-9]*.?[0-9] /[0-9]*.?[0-9] ',formula)
157     #     print(res)
158     #     for i in range(len(res)):
159     #         back = division(res[i])
160     #         res[i]=back
161     #     print("现在res又变成了",res)
162     #     for i in range(len(res)):
163     #         print(re.search('[0-9]*.?[0-9] /[0-9]*.?[0-9] ',formula))
164     #         # formula = re.sub('[0-9]?.?[0-9] /d ',str(res[i]),formula,count=1)  #还有一个"/"没有匹配上
165     #         formula = re.sub('[0-9]*.?[0-9] /[0-9]*.?[0-9] ',str(res[i]),formula,count=1)
166     #     print("你再看》》》》》",formula)
167     # print(' '*50)
168 
169 
170     # #下面开始算加
171     # while ' ' in formula:
172     #     res = re.findall('[0-9] .?[0-9]* [0-9] .?[0-9]*',formula)
173     #     print(res)
174     #     for i in range(len(res)):
175     #         back = addition(res[i])
176     #         res[i] = back
177     #
178     #     for i in range(len(res)):
179     #         formula= re.sub('[0-9] .?[0-9]* [0-9] .?[0-9]*',str(res[i]),formula,count=1)
180     #     print("你再看》》》》》", formula)
181     #
182     # #下面开始算减法
183     # print("-"*50)
184     # if '-' in formula:
185     #     res = re.findall('[0-9] .?[0-9]*-[0-9] .?[0-9]*',formula)
186     #     print(res)
187     #     for i in range(len(res)):
188     #         back = subtraction(res[i])
189     #         res[i] = back
190     #
191     #     for i in range(len(res)):
192     #         formula = re.sub('[0-9] .?[0-9]*-[0-9] .?[0-9]*',str(res[i]),formula,count=1)
193     #     print("你再看》》》》》", formula)
194     #
195 
196 
197 s = "1 - 2 * ( (60-30  (-40/5) * (9-2*5/3   7 /3*99/4*2998  10 * 568/14 )) - (-4*3)/ (16-3*2) )"
198 #先去掉空格
199 s = s.replace(' ','')
200 res = re.findall('([^()] )',s)
201 # print(res[3])
202 # count(res[3])
203 
204 for i in range(len(res)):
205     back = count(res[i])
206     print(back)
207     back = re.findall('[^((] (?=[))])',back)
208     print(back[0])
209     s = s.replace(res[i],str(back[0]))
210     print("最后算式是",s)
211 
212 s = re.sub(' -','-',s)
213 s = s.replace('--',' ')
214 
215 print('第一轮结果的算式',s)
216 
217 res = re.findall('([^()] )',s)
218 for i in range(len(res)):
219     back = count(res[i])
220     print(back)
221     back = re.findall('[^((] (?=[))])',back)
222     print(back[0])
223     s = s.replace(res[i],str(back[0]))
224 print("最后算式是",s)
225 
226 s = re.sub(' -','-',s)
227 s = s.replace('--',' ')
228 
229 print('第二轮结果的算式',s)
230 # print(res)
231 
232 res = re.findall('([^()] )',s)
233 for i in range(len(res)):
234     back = count(res[i])
235     print(back)
236     back = re.findall('[^((] (?=[))])',back)
237     print(back[0])
238     s = s.replace(res[i],str(back[0]))
239 print("最后算式是",s)
240 
241 s = re.sub(' -','-',s)
242 s = s.replace('--',' ')
243 
244 print('第三轮结果的算式',s)
245 
246 print(re.findall('([^()] )',s))
247 count(s)
248 
249 
250 
251 
252 
253 
254 
255 
256 
257 
258 
259 # print('look the space',''.join(s.split()))        #两种方法去掉字符串中所有的空格
260 # print('look the space',s.replace(' ',''))
261 
262 
263 
264 
265 
266 
267 
268 
269 
270 # s = '1 (3 4*(4 2))-(4-3*3)'
271 # print(s)
272 #
273 # res = re.findall('([^()] )',s)
274 # print(re.findall('[^()]',s))
275 # print(res)
276 #
277 # print(re.findall('[^f]',s))
278 #
279 #
280 #
281 #

View Code

大神Alex的代码--->https://www.cnblogs.com/alex3714/articles/5169958.html

0 人点赞