Py西游攻关之正则表达式
一简介
就其本质而言,正则表达式(或 RE)是一种小型的、高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。
二 元字符
字符匹配(普通字符,元字符):
1 普通字符:大多数字符和字母都会和自身匹配
>>> re.findall('alex','yuanaleSxalexwupeiqi')
['alex']
2 元字符: . ^ $ * + ? { } [ ] | ( ) \
没有元字符,正则表达式什么都不是!那接下来咱们就研究下元字符。
2.1 (贪婪匹配)
从前面的描述可以看到'*','+'和'?'都是贪婪的,但这也许并不是我们说要的,所以,可以在后面加个问号,将策略改为非贪婪,只匹配尽量少的RE。示例,体会两者的区别:
>>> re.findall(r"a(\d+?)","a23b") # 非贪婪模式
['2']
>>> re.findall(r"a(\d+)","a23b")
['23']
>>> re.search('<(.*)>', '<H1>title</H1>').group()
'<H1>title</H1>'
re.search('<(.*?)>', '<H1>title</H1>').group()
'<H1>'
注意比较这种情况:
>>> re.findall(r"a(\d+)b","a23b")
['23']
>>> re.findall(r"a(\d+?)b","a23b") #如果前后均有限定条件,则非匹配模式失效
['23']
2.2 (元字符[])
[]:它们常用来指定一个字符类别,所谓字符类就是你想匹配的一个字符集。字符可以单个列出,也可以用“-”号分隔的两个给定字符来表示一个字符区间。例如,[abc] 将匹配"a", "b", 或 "c"中的任意一个字符;也可以用区间[a-c]来表示同一字符集,和前者效果一致。如果你只想匹配小写字母,那么 RE 应写成 [a-z].元字符在类别里并不起作用。例如,[akm$]将匹配字符"a", "k", "m", 或 "$" 中的任意一个;"$"通常用作元字符,但在字符类别里,其特性被除去,恢复成普通字符。
例: re.search("[\d]","abc3").group()
2.3 (元字符 \ )
反斜杠后边跟元字符去除特殊功能,反斜杠后边跟普通字符实现特殊功能。
计算器:
import re def add_op(arg): # 定义加法函数 arg = arg.replace("++", "+").replace("--", "+").replace("+-", "-").replace("-+", "-") # 替换符号 num = re.findall("([+\-]?\d+\.?\d*)", arg) #匹配所有数字 result = 0 for i in num: #循环数字列表进行累加 result = result + float(i) return result def mul(arg): #定义乘除函数 while True: result = re.split("(\d+\.?\d*[\*/][\+-]?\d+\.?\d*)",arg,1) #匹配乘法或除法 if len(result) == 3: bef,cen,aft = result if "*" in cen: #判断乘号是否在cen里面 num1,num2 = cen.split("*") #将乘号进行分割得到乘数 new_cen = float(num1) * float(num2) #将乘数相乘得到乘积 arg = bef +str(new_cen) + aft #将乘积放入新的字符串表达式 elif "/" in cen: #判断除号是否在cen里面 num1,num2 = cen.split("/") #分割除号得到除数和被除数 new_cen = float(num1) / float(num2) #进行除法运算 arg = bef + str(new_cen) + aft #将商放入新的字符串表达式 else: return add_op(arg) def calc(arg): while True: arg = arg.replace(" ","") result = re.split("\(([^()]+)\)",arg,1) #匹配最里面的括号并且只取括号中的内容 if len(result) == 3: bef,cen,aft = result # 计算括号中的表达式,先乘除后加减,得到计算结果 r = mul(cen) #使用计算结果组成新的字符串表达式 arg = bef + str(r) + aft else: #计算完括号后开始按照先乘除再加减的运算 return mul(arg) origin = "1 - 2 * ( (60 - 30 + (-40.0/5) * 3))" r = calc(origin) print(r) print(eval(origin))