1. 程式人生 > >week4:函式之正則表示式

week4:函式之正則表示式

一、正則表示式

string提供的方法是完全匹配

引入正則表示式是模糊匹配,內嵌在python中,通過呼叫Re模組來實現

二、字元匹配(普通字元,元字元):

普通字元:大多數字符和字母都會和自身匹配

re.findall('alex','yuanalesalexduye') ## 完全匹配

元字元:.   ^   $  *  +  ?   {}   []   |  () \

import re
ret = re.findall('w\w{2}l', 'hello world')  #['worl']
print(ret)
import re
#. 萬用字元
ret = re.findall('w..l', 'hello world')
print(ret)  ##['worl']  只能代指任意一個字元  不能代指換行符
import re
ret = re.findall('^w..l', 'wuylhello world')
print(ret)  ##['wuyl']  從開始匹配
import re
ret = re.findall('w..l$', 'wuylhello world')
print(ret)  ##[]  從結束匹配
import re
# * 重複匹配 [0 oo]  重複前面字元的個數 貪婪匹配
ret = re.findall('w.*l', 'wuylhello world')
print(ret)  ##
import re
# + 重複匹配 [1 oo]  貪婪匹配
ret = re.findall('w+l', 'wwlhello world')
print(ret)  ##
# ? 重複匹配 [0 1]
# {n} n匹配
#{n1,n2} n1 n2匹配 貪婪匹配
# [] 字符集  取消元字元的特殊功能(\ ^ -這3個字元例外)
import re
ret = re.findall('a[c,d]x', 'acx')
print(ret)##['acx']
#-放在[]裡,代表範圍
ret1 = re.findall('[a-z]x', 'acx')
print(ret1) #['cx']
ret3 = re.findall('[1-9a-zA-Z]', '12tyAS')
print(ret3) #['1', '2', 't', 'y', 'A', 'S']
ret4 = re.findall('[1-9,a-z,A-Z]', '12tyAS')
print(ret4) #['1', '2', 't', 'y', 'A', 'S']
#特殊字元. * 沒有特殊意義
ret2 = re.findall('[w,*]x', 'acx')
print(ret2) #[]

#^放在[]裡,代表取反
ret5 = re.findall('[^4,5]', 'ju12tyA5i4,us')
print(ret5) #['j', 'u', '1', '2', 't', 'y', 'A', 'i', 'u', 's']

# \ 後邊跟元字元,去特殊功能
#\ 後邊跟普通字元,實現特殊功能
ret6 = re.findall('\d{11}', 'ju12tyA5i498234567812345678')
print(ret6) #['j', 'u', '1', '2', 't', 'y', 'A', 'i', 'u', 's']
ret7 = re.findall(r'I\b', 'I am a LIST')
print(ret7) #['I']
#匹配出第一個滿足條件的結果
ret8 = re.search('s.b', 'fjaskdseb')
print(ret8.group()) #seb

ret9 = re.search('a\.', 'agj')
print(ret9.group()) #此時沒有匹配成功 

import re
# ()|
ret9 = re.search('(as)+', 'agjasas')
print(ret9.group())
ret10 = re.search('(as)|3', '3agjasas')
print(ret10.group())  ##3

 三、正則表示式的方法

1、findall()  所有的結果都返回到一個列表裡

2、search() 返回匹配到的第一個物件(object),物件可以呼叫group返回結果

3、match()  只在字串開始匹配,物件可以呼叫group返回結果

import re
ret = re.match('asd', 'asdfeuyrt')
print(ret.group())

4、split()

import re
ret = re.split('[j,s]', 'djksal')
print(ret)

 5、sub()

import re
ret = re.sub('a..x', 's..b', 'djkalexsal')
print(ret)  ##djks..bsal

 6.compile()

import re
obj = re.compile('.com')
ret = obj.findall('djkal.comexsal')
print(ret)  ##['.com']

四、正則表示式的應用

計算器的設計

import re

#格式化字串
def format_string(string):
    string = string.replace('--', '+')
    string = string.replace('-+', '-')
    string = string.replace('++', '+')
    string = string.replace('+-', '-')
    string = string.replace('*+', '*')
    string = string.replace('/+', '/')
    string = string.replace(' ', '')
    return string


#檢查表示式合法性
def check_expression(string):
    check_result = True
    #括號是否匹配
    if not string.count('(') == string.count(')'):
        print('表示式錯誤,括號未閉合')
        check_result = False
    if re.findall('[a-z]+]',string.lower()):
        print('表示式錯誤,包含非法字元')
        check_result = False

    return check_result


#計算乘除
def calc_mul_div(string):
    #從字串中獲取一個乘法或除法的表示式
    regular = '[\-]?\d+\.?\d*([*/]|\*\*)[\-]?\d+\.?\d*'
    #如果還能找到乘法或除法表示式
    while re.findall(regular, string):
        #獲取表示式
        expression = re.search(regular, string).group()

        #如果是乘法
        if expression.count('*')==1:
            #獲取要計算的兩個數
            x, y = expression.split('*')
            #計算結果
            mul_result = str(float(x)*float(y))
            #將計算的表示式替換為計算結果值
            string = string.replace(expression, mul_result)
            #格式化以下
            string = format_string(string)


        #如果是除法
        if expression.count('/'):
            #獲取要計算的兩個數
            x, y = expression.split('/')
            #計算結果
            div_result = str(float(x)/float(y))
            #將計算的表示式替換為計算結果值
            string = string.replace(expression, div_result)
            #格式化以下
            string = format_string(string)


        if expression.count('*')==2:
            #獲取要計算的兩個數
            x, y = expression.split('**')
            pow_result=1
            for i in range(int(y)):
                pow_result *= int(x)
            string = string.replace(expression, str(pow_result))
            #格式化以下
            string = format_string(string)
    return string

#計算加減
def calc_add_sub(string):
    #定義正則表示式
    add_regula = '[\-]?\d+\.?\d*\+[\-]?\d+\.?\d*'
    sub_regula = '[\-]?\d+\.?\d*\-[\-]?\d+\.?\d*'


    #開始加法
    while re.findall(add_regula, string):
        #把所有的加法都算完,獲取所有加法表示式
        add_list = re.findall(add_regula, string)
        for add_str in add_list:
            #獲取兩個加法的數
            x, y = add_str.split('+')
            add_result = '+' + str(float(x)+float(y))
            string = string.replace(add_str, add_result)
            string = format_string(string)

    # 開始減法
    while re.findall(sub_regula, string):
        #把所有的加法都算完,獲取所有加法表示式
        sub_list = re.findall(sub_regula, string)
        for sub_str in sub_list:
            numbers = sub_str.split('-')
            #-3-5的情況,split會返回3個值
            if len(numbers) == 3:
                result = 0
                for v in numbers:
                    if v:
                        result -= float(v)
            else:
                x, y =numbers
                result = float(x)-float(y)
                #替換字串

            string = string.replace(sub_str, '+' + str(result))
            string = format_string(string)
    return string


if __name__ == "__main__":

    source = "30-2*(6-3+(-9+2*3-4*4/2+6*3))"
    if check_expression(source):
        print('source:', source)
        print('eval result:', eval(source))
        source = format_string(source)
        print(source)

        while source.count('(') > 0:
            ## 格式化
            ##去括號,得到括號的字串,結果如:(30+6/3)
            strs = re.search('\([^()]*\)', source).group()
            # 將括號的表示式進行乘除運算
            replace_str = calc_mul_div(strs)
            # 將括號的表示式進行加減運算
            replace_str = calc_add_sub(replace_str)
            # 將括號的字串替換為計算結果,結果包含(),替換時去掉():[1:-1]
            source = format_string(source.replace(strs, replace_str[1:-1]))
        else:
            # 沒有括號就到最後單一表達式了
            replace_str = calc_mul_div(source)
            # 算乘除
            replace_str = calc_add_sub(replace_str)
            # 算加減
            source = source.replace(source, replace_str)
        print('my result:', source.replace('+', ''))

輸出結果:

source: 30-2*(6-3+(-9+2*3-4*4/2+6*3))
eval result: 10.0
30-2*(6-3+(-9+2*3-4*4/2+6*3))
my result: 10.0