python_正则表达式、正则函数、正则计算器

# ### 正则表达式 匹配单个字符
import re
"""
lst = re.findall(正则表达式,要匹配的字符串)
返回列表,按照正则表达式匹配到的内容都扔到列表里
"""

# ### 1.预定义字符集
# \d 匹配数字
lst = re.findall("\d","asdlfkjasdklfjkla_()()*(*(23423sdf4")
print(lst)


# \D 匹配非数字
lst = re.findall("\D","asdlfkjasdklfjkla_()()*(*(23423sdf4")
print(lst)

# \w 匹配字母或数字或下划线     (正则函数中,支持中文的匹配)
lst = re.findall("\w","sdf&&&s9%%89!!!_你好")
print(lst)

# \W 匹配非字母或数字或下划线
lst = re.findall("\W","sdf&&&s9%%89!!!_你好")
print(lst)

# \s 匹配任意的空白符 \n \t \r ' '
lst = re.findall("\s","  			")
print(lst)

# \S 匹配任意非空白符
lst = re.findall("\S" , "  aa 	bb")
print(lst)

# \n 匹配一个换行符
strvar = """
xboy 他是一个 神秘男孩 
"""
lst = re.findall(r"\n",strvar)
print(lst)
strvar = """
xboy 他是一个 神秘			男孩 		
"""
lst = re.findall(r"\t",strvar)
print(lst)

# ### 2.字符组 必须匹配中括号里列举的字符[]
lst = re.findall("[abc]","oputuopctyauobpt")
print(lst)

print(re.findall('a[abc]b','aab abb acb adb')) # aab abb acb

print(re.findall('a[0123456789]b','a1b a2b a3b acb ayb'))#a1b a2b a3b 
# 优化: -是一个特殊的字符,代表的是一个范围 0-9 0123456789
print(re.findall('a[0-9]b','a1b a2b a3b acb ayb'))#a1b a2b a3b 

print(re.findall('a[abcdefg]b','a1b a2b a3b acb ayb adb')) #acb adb
# 优化: [a-g]  如果想要表达所有的26个小写字母[a-z]
print(re.findall('a[a-g]b','a1b a2b a3b acb ayb adb')) #acb adb

print(re.findall('a[ABCDEFG]b','a1b a2b a3b  aAb aDb aYb')) #aAb aDb
# 优化: [A-G]  如果想要表达所有的26个大写字母[A-Z]
print(re.findall('a[A-G]b','a1b a2b a3b  aAb aDb aYb')) #aAb aDb


print(re.findall('a[0-9a-zA-Z]b','a-b aab aAb aWb aqba1b')) #aab aAb aWb aqb a1b
# 注意: [0-z] 数字 小写 大写 还有特殊字符 比如@ ... 
print(re.findall('a[0-z]b','a@b aab aAb aWb aqba1b')) #aab aAb aWb aqb a1b

print(re.findall('a[0-9][*#/]b','a1/b a2b a29b a56b a456b')) # a1/b

# ^ 在字符组当中, 代表除了 放到字符组的左边第一个位置
print(re.findall('a[^-+*/]b',"a%b ccaa*bda&bd")) # a%b a&b

# 如果想要匹配^ 或者 -, 在原来的字符前面加上\,让字符的含义失效.
lst = re.findall(r"e[\^\-]f","e^f e-f")
print(lst)

# 匹配 \
lst = re.findall(r"a\\c","a\c")
print(lst)
print(lst[0])

"""
res = re.findall(r'a\\b',r'a\b')
res = re.findall(r'a\\n',r'a\n')
print(res)
print(res[0])
# \b -> 转义字符 backspace


# a[\^\\]b  a^b  a\b 这个出来的怎么只有a^b
res = re.findall(r"a[\^\\]b",r"a^b a\b")
print(res) # ['a^b', 'a\\b']
print(res[1])
"""

```python
# ### 正则表达式 多个字符的匹配
import re
# 量词练习
'''1) ? 匹配0个或者1个a '''
print(re.findall('a?b','abbzab abb aab'))  # ab  b ab ab b ab
'''2) + 匹配1个或者多个a '''
print(re.findall('a+b','b ab aaaaaab abb')) # ab aaaaaab ab
'''3) * 匹配0个或者多个a '''
print(re.findall('a*b','b ab aaaaaab abbbbbbb')) # b ab aaaaaab ab b b b b b b
'''4) {m,n} 匹配m个至n个a '''
# (1) 1 <= x <= 3
print(re.findall('a{1,3}b','aaab ab aab abbb aaz aabb')) # aaab ab aab ab aab
# (2) 前面修饰的a , 必须是2个字符
print(re.findall('a{2}b','aaab ab aab abbb aaz aabb')) # aab aab aab
# (3) 前面修饰的a , 至少是2个字符
print(re.findall('a{2,}b','aaab ab aab abbb aaz aabb')) # aaab aab aab


# ### 2.贪婪模式 与 非贪婪模式
"""
贪婪模式 与 非贪婪模式:
	贪婪模式 :  默认向更多次匹配,底层用的是回溯算法
	非贪婪模式: 默认向更少次匹配,用一个?号来进行修饰(修饰在量词的身后)
	
	回溯算法: 从左向右进行匹配,一直到最后,直接最后再也匹配不到了,回头,寻找最后一个

	. 匹配任意字符,除了换行符\n
"""
strvar = "刘能和刘老根和刘铁棍子777子888"
lst = re.findall("刘.",strvar)
print(lst) # ['刘能', '刘老', '刘铁']

# 贪婪模式
lst = re.findall("刘.?",strvar)
print(lst) # ['刘能', '刘老', '刘铁']

lst = re.findall("刘.+",strvar)
print(lst) # ['刘能和刘老根和刘铁棍子777子888']

lst = re.findall("刘.*",strvar)
print(lst) # ['刘能和刘老根和刘铁棍子777子888']

lst = re.findall("刘.{1,21}",strvar)
print(lst) # ['刘能和刘老根和刘铁棍子777子888']

lst = re.findall("刘.*子",strvar)
print(lst) # ['刘能和刘老根和刘铁棍子777子']

# 非贪婪模式
lst = re.findall("刘.??",strvar)
print(lst) # ['刘', '刘', '刘']

lst = re.findall("刘.+?",strvar)
print(lst) # ['刘能', '刘老', '刘铁']

lst = re.findall("刘.*?",strvar)
print(lst) # ['刘', '刘', '刘']

lst = re.findall("刘.{1,21}?",strvar)
print(lst) # ['刘能', '刘老', '刘铁']

lst = re.findall("刘.*?子",strvar)
print(lst) # ['刘能和刘老根和刘铁棍子']

# ### 3.边界符 \b ^ $
"""
\b backspace 本身就是一个转义字符
边界符 卡单词 word
	卡住左边界 \bw
	卡住右边界 d\b
"""
strvar = "word pwd scf"
lst = re.findall(r".*d\b",strvar)
print(lst) # ['word pwd']

lst = re.findall(r".*?d\b",strvar)
print(lst) # ['word', ' pwd']

lst = re.findall(r"\bw",strvar)
print(lst) # ['w']

lst = re.findall(r"\bw.*?",strvar)
print(lst) # ['w']

# 正则表达式中写字符时,要谨慎,下面例子必须匹配到第一个空格时,才结束
lst = re.findall(r"\bw.*? ",strvar)
print(lst) # ['word ']

lst = re.findall(r"\bw\S*",strvar)
print(lst) # ['word']


# ^ $ 
"""
^ 必须以..开头
$ 必须以..结尾
如果出现了^ $ , 要把这个字符串看成一个整体
"""
strvar = "大哥大嫂大爷"
print(re.findall('大.',strvar))  # ['大哥', '大嫂', '大爷']
print(re.findall('^大.',strvar)) # ['大哥']
print(re.findall('大.$',strvar)) # ['大爷']
print(re.findall('^大.$',strvar))# []
print(re.findall('^大.*?$',strvar)) # ['大哥大嫂大爷']
print(re.findall('^大.*?大$',strvar)) # []
print(re.findall('^大.*?爷$',strvar)) # ['大哥大嫂大爷']


print(re.findall('^g.*? ' , 'giveme 1gfive gay')) # ['giveme ']
print(re.findall('five$' , 'aassfive'))  # five
print(re.findall('^giveme$' , 'giveme')) # giveme
print(re.findall('^giveme$' , 'giveme giveme'))# []
print(re.findall('giveme' , 'giveme giveme')) # ['giveme', 'giveme']
print(re.findall("^g.*e",'giveme 1gfive gay')) # ['giveme 1gfive']

# ### 正则表达式  命名分组
import re
strvar = "<div>明天就放假了,很开心</div>"

# 当不清楚字符串中含有什么内容时,用.*?进行取代
lst = re.findall(r"<(.*?)>(.*?)<(.*?)>",strvar)
print(lst) # [('div', '明天就放假了,很开心', '/div')]

# (1) 反向引用
# \1 代表反向引用,将第一个括号匹配的字符串,在\1位置处在引用一次
lst = re.findall(r"<(.*?)>(.*?)<(/\1)>",strvar)
print(lst)  # [('div', '明天就放假了,很开心', '/div')]

# \1 代表第一个括号  \2代表第二个括号
strvar = "a1b2cab"
obj = re.search(r"(.*?)\d(.*?)\d(.*?)\1\2",strvar)
print(obj)
# 返回匹配到的字符串
res = obj.group()
print(res)
# 返回匹配到的分组内容
res = obj.groups()
print(res)

# (2) 命名分组
"""
# 2.命名分组 (给小组命名)
3) (?P<组名>正则表达式) 给这个组起一个名字
4) (?P=组名) 引用之前组的名字,把该组名匹配到的内容放到当前位置
"""

# 方法一
strvar = "a1b2cab"
obj = re.search(r"(?P<tag1>.*?)\d(?P<tag2>.*?)\d(?P<tag3>.*?)\1\2",strvar)
print(obj.group()) # a1b2cab

# 方法二
strvar = "a1b2cab"
obj = re.search(r"(?P<tag1>.*?)\d(?P<tag2>.*?)\d(?P<tag3>.*?)(?P=tag1)(?P=tag2)",strvar)
print(obj.group()) # a1b2cab

# ### 正则表达式 匹配分组
import re
# ### 1.分组练习(用圆括号) 要所有的姓名
print(re.findall('.*?_good','wusir_good alex_good secret男_good'))
# ['wusir_good', ' alex_good', ' secret男_good']


# () 显示括号里面匹配到的内容
print(re.findall('(.*?)_good','wusir_good alex_good secret男_good'))
# ['wusir', ' alex', ' secret男']
# ?: 不显示括号里面的内容
print(re.findall('(?:.*?)_good','wusir_good alex_good secret男_good'))
# ['wusir_good', ' alex_good', ' secret男_good']


# ### 2.| 代表或 , a|b 匹配字符a 或者 匹配字符b 
# 基本语法
strvar = "abcddd"
lst = re.findall("a|b",strvar) 
print(lst)
# 注意事项
# 匹配abc 或者 abcd
"""
为了避免优先匹配前面的字符串,导致字符串匹配不完整,
把较难匹配到的字符串写在前面,容易匹配到的字符串放在后面
"""
strvar = "abc24234234ddabcd234234"
# lst = re.findall("abc|abcd",strvar) 注意
# print(lst) # ['abc', 'abc']
lst = re.findall("abcd|abc",strvar)
print(lst) # ["abc","abcd"]
 
 
# ### 3.练习
"""
.  除了\n,能够匹配到任意字符
\  功效: 让有意义的字符变得无意义,或者让无意义的字符变得有意义
\. 让点原来的特殊含义失效,只是单纯的表达一个点字符.
"""
# (1)匹配小数 
strvar = "5.33 3.13 34 34.  .98 9.99 sdfsdf  ......"
# 整数.小数
lst = re.findall(r"\d+\.\d+",strvar)
print(lst)

# (2)匹配小数和整数 
# 整数.小数 34 43234 .
# \d+
# \d+\.\d+ 
lst = re.findall(r"\d+\.\d+|\d+",strvar)
print(lst) # ['5.33', '3.13', '34', '34', '98', '9.99']

# 用分组形式来做 
"""
findall 这个函数优先显示括号里面的内容,
如果不想显示括号内容,使用?:, 显示实际匹配到的内容
"""
lst = re.findall(r"\d+(?:\.\d+)?",strvar)
print(lst) # ['5.33', '3.13', '34', '34', '98', '9.99']

# 匹配135或171的手机号 
strvar = "asdfasd234 13591199444 17188886666 19145547744"
lst = re.findall("(?:135|171)\d{8}",strvar)
print(lst)

# 卡主开头和结尾,数字必须是11位
strvar = "13591199444"
lst = re.findall("^(?:135|171)[0-9]{8}$",strvar)
print(lst)

# ### search 函数
"""
findall  把所有匹配到的字符串都搜出来,返回列表
		 不能把分组内容和匹配的内容同时显示出来
		 
		 
search   只要搜索到一个结果就返回,返回对象.
	     可以把分组内容和匹配的内容同时显示出来
		 
group : 对象.group()  直接获取匹配到的内容
groups: 对象.groups() 直接获取分组里面的内容
"""
# 匹配www.baidu.com 或者 www.oldboy.com
strvar = "www.baidu.com"
lst = re.findall("(?:www)\.(?:baidu|oldboy)\.(?:com)",strvar)
print(lst)

obj = re.search("(www)\.(baidu|oldboy)\.(com)",strvar)
print(obj)
# 获取的是匹配到的数据
print(obj.group())
# 获取的是分组里面的数据
print(obj.groups())

# 获取第一个小括号里面的内容
print(obj.group(1))
# 获取第二个小括号里面的内容
print(obj.group(2))
# 获取第三个小括号里面的内容
print(obj.group(3))

# ### 案例: "5*6-7/3" 匹配 5*6 或者 7/3
"""search 在匹配不到时,返回的是None,无法使用group"""

# 匹配出5*6
strvar = "5*6-7/3"

# 匹配出5*6
obj = re.search(r"\d+[*/]\d+",strvar)
print(obj)
strvar1 = obj.group()
print(strvar1) # 5*6

# 按照*号分隔,算出乘积结果
n1,n2 = strvar1.split("*")
res1 = int(n1)*int(n2)
print(res1)

# 对字符串进行替换
# strvar = "30-7/3"
strvar2 = strvar.replace(strvar1,str(res1))
print(strvar2) # 30-7/3

# 匹配出 7/3
obj = re.search(r"\d+[*/]\d+",strvar2)
strvar3 = obj.group()
print(strvar3) # 7/3

# 按照/号分隔,算出除法结果
n1,n2 = strvar3.split("/")
res2 = int(n1)/int(n2)
print(res2)

# 对字符串进行替换
strvar4 = strvar2.replace(strvar3,str(res2))
print(strvar4)

# 通过-号进行最后的分隔,算出最后的结果.
n1,n2 = strvar4.split("-")
res_finally = float(n1) - float(n2)
print(res_finally)

# ### 正则函数
import re
# search   通过正则匹配出第一个对象返回,通过group取出对象中的值
strvar = "1+2 3*4"
obj = re.search("\d+(.*?)\d+",strvar)
# 返回匹配到的内容(匹配到一个就返回)
print(obj.group()) # 1+2
# 把括号里匹配到的内容扔到元组中返回
res = obj.groups()
print(res)

# match    验证用户输入内容 (了解)
"""search 只要在正则表达式的前面加上^ 就和match 一模一样"""
strvar = "y13566688771"
strvar = "13566688771"
obj = re.search("^\d+",strvar)
print(obj.group()) # 13566688771

obj = re.match("\d+",strvar)
print(obj.group()) 


# split    切割
strvar = "alex|xboy&wusir-egon"
res = re.split("[|&-]",strvar)
print(res) # ['alex', 'xboy', 'wusir', 'egon']

strvar = "alex23423411122334xboyww90909045wusir78"
res = re.split("\d+",strvar)
print(res) # ['alex', 'xboyww', 'wusir', '']


# sub      替换 (正则表达式,替换的字符串,原字符串,[可选的替换次数])
strvar = "alex|xboy&wusir-egon"
# strvar.replace("|","%")
# strvar.replace("&","%")
# strvar.replace("-","%")

res = re.sub("[|&-]","%",strvar)
print(res) # alex%xboy%wusir%egon
res = re.sub("[|&-]","%",strvar,1)
print(res) # alex%xboy&wusir-egon

# subn     替换 与sub 用法一样,区别在于返回值不同,返回的是元组
res = re.subn("[|&-]","%",strvar)
print(res) # ('alex%xboy%wusir%egon', 3)
res = re.subn("[|&-]","%",strvar,1)
print(res) # ('alex%xboy&wusir-egon', 1)


 
# finditer 匹配字符串中相应内容,返回迭代器
from collections import Iterator
strvar = "sdfasf234234你好23423"
it = re.finditer(r"\d+",strvar)
print(isinstance(it,Iterator))
"""
lst = list(it)
print(lst)
[
<_sre.SRE_Match object; span=(6, 12), match='234234'>, 
<_sre.SRE_Match object; span=(14, 19), match='23423'>
]

234234
23423
"""
for i in it:
	print(i.group())


# compile  指定一个统一的匹配规则
"""
正常情况下,正则表达式执行一次,编译一次
如果需要反复使用,会浪费系统资源,比如内存,cpu

compile 可以使正则编译一次,终身受益,无需反复编译
"""
strvar = "sdfasf234234你好23423"
pattern = re.compile("\d+")
print(pattern) # re.compile('\\d+')



obj = pattern.search(strvar)
print(obj.group()) # 234234
lst = pattern.findall(strvar)
print(lst) # ['234234', '23423']


# 修饰符
# re.I 使匹配对大小写不敏感
strvar = "<h1>123</H1>"
pattern = re.compile("<h1>(.*?)</h1>",flags=re.I)
obj = pattern.search(strvar)
print(obj)
print(obj.group()) # <h1>123</H1>


# re.M 使每一行都能够单独匹配(多行匹配),影响 ^ 和 $
strvar = """<h1>123</H1>
<p>123</p>
<div>123</div>
"""

pattern = re.compile("^<.*?>(?:.*?)<.*?>$",flags=re.M)
print(pattern.findall(strvar)) # ['<h1>123</H1>', '<p>123</p>', '<div>123</div>']


# re.S 使 . 匹配包括换行在内的所有字符
strvar = """give
1112233mefive
"""
pattern = re.compile("(.*?)mefive",flags=re.S)
obj = pattern.search(strvar)
print(obj.group()) # 1112233mefive
"""
	give
	1112233mefive
"""

# ### 正则计算器
import re
strvar = "1-2*((60-30+(-40/5)*(9-2*5/3+7/3*99/4*2998+10*568/14))-(-4*3)/(16-3*2))" # 2776672.6952380957
# strvar = "-30+(40+5*-2+3/2)*8 +       (4-  7)  "

print(eval(strvar)) # 2776672.6952380957


# 处理符号
def sign_exp(strvar):
	strvar = strvar.replace("+-","-")
	strvar = strvar.replace("--","+")
	strvar = strvar.replace("-+","-")
	strvar = strvar.replace("++","+")
	return strvar
	
# 计算表达式
def calc_exp(strvar):
	# 判断字符串是 乘法 还是 除法
	if "*" in strvar:
		a,b = strvar.split("*")
		return float(a) * float(b)
		
	if "/" in strvar:
		a,b = strvar.split("/")
		return float(a) / float(b)

# 操作表达式
def opreate_exp(strvar):
	# 先算乘除
	while True:
		# (40+5*-2+3/2)
		# 匹配 [谁*谁]  或者 [谁/谁]  例: 5*-2 3/2
		obj = re.search(r"\d+(\.\d+)?[*/][+-]?\d+(\.\d+)?",strvar)
		if obj:
			res1 = obj.group()
			# print(res1) # 5*-2
			# 计算表达式的结果
			res2 = calc_exp(res1)
			# print(res2 , type(res2)) # -10.0 <class 'float'>
			# 将所得的结果,替换到原来的字符串当中,以匹配下一个乘法或者除法
			strvar = strvar.replace(res1,str(res2))
			# print(strvar) # (40+-10.0+3/2)
		else:
			# 当obj 返回None的时候停止
			break
			
	# 处理表达式中的符号
	strvar = sign_exp(strvar)
	# print(strvar) # (40+-10.0+1.5)  (40-10.0+1.5)
	
	# 计算剩下+-的表达式(将每一个数字匹配出来,做累加)
	lst = re.findall("[+-]?\d+(?:\.\d+)?",strvar)
	# print(lst) # ['40', '-10.0', '+1.5']
	total = 0
	for i in lst:
		total += float(i)
	# print(total) # 31.5
	return total
		

# 移除括号
def remove_bracket(strvar):
	while True:
		obj = re.search("\([^()]+\)",strvar)
		# print(obj)
		if obj:
			res1 = obj.group()
			# print(res1) # (40+5*-2+3/2)   "-30+(40+5*-2+3/2)*8 +(4-7)"
			# 计算一个括号里面表达式的值
			res2 = opreate_exp(res1)
			# print(res2) # 31.5
			# 替换原来的括号,消除括号
			strvar = strvar.replace(res1,str(res2))
			# print(strvar) # -30+31.5*8+(4-7)
		else:
			return strvar # 返回一串没有括号的表达式



# main函数当中不写逻辑,只调用相关的功能
def main(strvar):
	# 1.整理数据,把没用的空格去掉
	strvar = strvar.replace(" ","")
	# 2.移除所有括号
	strvar = remove_bracket(strvar)
	# print(strvar) # -30+31.5*8+-3.0
	# 3.计算表达式
	return opreate_exp(strvar)

res = main(strvar)
print(res) # 219.0

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值