正则表达式
正则表达式是对字符串操作的一种逻辑公式.我们一般使用正则表达式对字符串进行匹配和过滤.
使用正则的优缺点:
优点: 灵活, 功能性强, 逻辑性强.
缺点: 上手难. 一旦上手, 会爱上这个东西
元字符
'.' 默认匹配除\n之外的任意一个字符,若指定flag DOTALL, 则匹配任意字符,包括换行
'^' 匹配字符开头,若指定flags MULTILINE, 这种也可以匹配上(r"^a", "\nabc\neee", flags=re.MULTILINE)
'$' 匹配字符结尾,或e.search("foo$", "bfoo\nsdfsf", flags=re.MULTILINE).group()也可以
'|' 匹配 | 左或 | 右的字符,re.search("abc|ABC", "ABCBabcCD").group()结果 'ABC'
'(...)' 分组匹配,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\tc1\n3").group()结果'\t'' \
量词
'*' 匹配 * 号前的字符0次或多次,
'+' 匹配前一个字符1次或多次,
'?' 匹配前一个字符1次或0次,尽可能的少
'{m}' 匹配前一个字符m次
'{n,m}' 匹配前一个字符n到m次,
转义
在正则:
\.
\元字符
python
"\\."
r"\."
惰性匹配
* + {} 都是贪婪匹配,尽可能多的匹配到结果
.? +? {}? ,惰性匹配,尽可能少的匹配
量词后面加问号
.*?abc 一直取遇到abc就停
分组
() 优先级最高
/1 再次匹配第一个分组
1 import re
2
3 # 常用语法:
4 # re.findall 把所有匹配到的字符放到以列表中的元素返回
5 # re.finditer() # 与findall相同,返回的是迭代器
6 # re.search 会进行匹配. 但是如果匹配到了第一个结果. 就会返回这个结果. 如果匹配不上search返回的则是None
7 # re.match 从头开始匹配
8 # re.splitall 以匹配到的字符当做列表分隔符
9 # re.sub 匹配字符并替换
10 # compile 编译 :正则表达式很长且要多次使用
11
12
13 # ret = re.findall('[a-z]+', 'eva egon yuan')
14 # 返回所有满足匹配条件的结果,放在列表里
15 # print(ret) # ['eva', 'egon', 'yuan']
16
17 # ret = re.search('a', 'eva egon yuan')
18 # if ret:
19 # print(ret.group())
20 # # 从前往后,找到一个就返回,返回的变量需要调用group才能拿到结果
21 # # 如果没有找到,那么返回None,调用group会报错
22
23 # ret = re.match('[a-z]+', 'eva egon yuan')
24 # if ret:
25 # print(ret.group())
26 # match是从头开始匹配,如果正则规则从头开始可以匹配上,就返回一个变量。
27 # 匹配的内容需要用group才能显示
28 # 如果没匹配上,就返回None,调用group会报错
29
30 # ret = re.split('[ab]', 'abcd')
31 # # # 先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割
32 # print(ret) # ['', '', 'cd']
33
34 # ret = re.sub('\d', 'H', 'eva3egon4yuan4',1)
35 # 将数字替换成'H',参数1表示只替换1个
36 # print(ret) #evaHegon4yuan4
37
38 # ret = re.subn('\d', 'H', 'eva3egon4yuan4')
39 # #将数字替换成'H',返回元组(替换的结果,替换了多少次)
40 # print(ret)
41
42 # obj = re.compile('\d{3}')
43 # #将正则表达式编译成为一个正则表达式对象,规则要匹配的是3个数字
44 # ret = obj.search('abc123eeee') #正则表达式对象调用search,参数为待匹配的字符串
45 # print(ret.group())
46 # ret = obj.search('abcashgjgsdghkash456eeee3wr2') #正则表达式对象调用search,参数为待匹配的字符串
47 # print(ret.group()) #结果 : 123
48
49 # ret = re.finditer('\d', 'ds3sy4784a') #finditer返回一个存放匹配结果的迭代器
50 # print(ret) # <callable_iterator object at 0x10195f940>
51 # for i in ret:
52 # print(i.group())
53
54 # ------------------元字符--------------------------
55
56 # '.' 默认匹配除\n之外的任意一个字符,若指定flag DOTALL, 则匹配任意字符,包括换行
57 # '^' 匹配字符开头,若指定flags MULTILINE, 这种也可以匹配上(r"^a", "\nabc\neee", flags=re.MULTILINE)
58 # '$' 匹配字符结尾,或e.search("foo$", "bfoo\nsdfsf", flags=re.MULTILINE).group()也可以
59 # '*' 匹配 * 号前的字符0次或多次,re.findall("ab*", "cabb3abcbbac")结果为['abb', 'ab', 'a']
60 # '+' 匹配前一个字符1次或多次,re.findall("ab+", "ab+cd+abb+bba")结果['ab', 'abb']
61 # '?' 匹配前一个字符1次或0次
62 # '{m}' 匹配前一个字符m次
63 # '{n,m}' 匹配前一个字符n到m次,re.findall("ab{1,3}", "abb abc abbcbbb")结果 'abb', 'ab', 'abb']
64 # '|' 匹配 | 左或 | 右的字符,re.search("abc|ABC", "ABCBabcCD").group()结果 'ABC'
65 # '(...)' 分组匹配,re.search("(abc){2}a(123|456)c", "abcabca456c").group()结果abcabca456c
66 #
67 # '\A' 只从字符开头匹配,re.search("\Aabc", "alexabc")是匹配不到的
68 # '\Z' 匹配字符结尾,同$
69 # '\d' 匹配数字0 - 9
70 # '\D' 匹配非数字
71 # '\w' 匹配[A - Za - z0 - 9]
72 # '\W' 匹配非[A - Za - z0 - 9]
73 # 's' 匹配空白字符、\t、\n、\r, re.search("\s+", "ab\tc1\n3").group()结果'\t'' \
74
75
76 # 分组命名
77 # (?P<name>...) The substring matched by the group is accessible by name.
78 # obj = re.compile(r'(?P<id>\d+)(?P<name>e+)') # 从正则表达式匹配的内容每个组起名字
79 # ret = obj.search('abc123eeee') # 搜索
80 # print(ret.group()) # 结果: 123eeee
81 # print(ret.group("id")) # 结果: 123 # 获取id组的内容
82 # print(ret.group("name")) # 结果: eeee # 获取name组的内容
83 # (...)与(?:...)
84 # () 获取匹配的结果
85 # (?:...) 不获取匹配的结果
86 # findall
87 # ret = re.findall('www.(baidu|oldboy).com', 'www.oldboy.com')
88 # print(ret) # ['oldboy']
89 # ret = re.findall('www.(?:baidu|oldboy).com', 'www.oldboy.com')
90 # print(ret) # ['www.oldboy.com'
91 # split
92 # ret=re.split("\d+","eva3egon4yuan")
93 # print(ret) #结果 : ['eva', 'egon', 'yuan']
94 # ret=re.split("(\d+)","eva3egon4yuan")
95 # print(ret) #结果 : ['eva', '3', 'egon', '4', 'yuan']
96 # # 在匹配部分加上()之后所切出的结果是不同的,
97 # # 没有()的没有保留所匹配的项,但是有()的却能够保留留了匹配的项,
98 # # 这个在某些需要保留匹配部分的使用过程是非常重要的。
99
100 # 其他(没做深入了解)
101 # (?=...) Matches if ... matches next, but doesn't consume the string.
102 # (?!...) Matches if ... doesn't match next.
103 # (?<=...) Matches if preceded by ... (must be fixed length).
104 # (?<!...) Matches if not preceded by ... (must be fixed length).
105
106 # -----------------------常见问题----------------------------------
107 # 转义的问题
108 # import re
109 # re.findall(r'\\s',r'\s')
110
111 # 惰性匹配
112 # 量词后面加问号
113 # .*?abc 一直取遇到abc就停
re模块
1 import re
2
3
4 def add_sub(equation):
5 """
6 计算加减算式,并返回结果
7 :param equation: 1+2,1-1
8 :return: float
9 """
10 # 这里用eval代替了计算加减的函数
11 return eval(equation)
12
13
14 def mul_div(equation):
15 """
16 计算加减乘除算式,返回结果。 两端带有括号,里面没有括号
17 :param equation: 包含有加减乘除的式子
18 :return: float
19 """
20 # (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )
21 equation = equation.strip('()')
22 equation = equation.replace('++', '+')
23 equation = equation.replace('+-', '-')
24 equation = equation.replace('-+', '-')
25 equation = equation.replace('--', '+')
26 while True:
27 if '*' in equation or '/' in equation:
28 old = re.search('[\d.]*[*/][-]?[\d.]*', equation)
29 equation = equation.replace(old.group(), str(eval(old.group())))
30 # 这里eval代替了计算乘除的函数,1*2,1/2,1*-1
31 else:
32 return add_sub(equation)
33
34
35 def analyze_cal(equation):
36 while True:
37 if '(' in equation:
38 old = re.search('\([^()]*\)', equation)
39 equation = equation.replace(old.group(), str(mul_div(old.group())))
40 else:
41 return mul_div(equation)
42
43
44 if __name__ == '__main__':
45 a = '1 - 2 * ( ( 6 0 -3 0 +(-40/5) * (9-2*5/3 + 7 /3*99/4*2998 +10 * 568/14 )) - (-4*3)/ (16-3*2) )'
46 a = a.replace(' ', '')
47 print(analyze_cal(a))
计算器-re