簡體   English   中英

用正則表達式解析算術字符串

[英]Parse arithmetic string with regular expression

我只需要用一次* )解析算術字符串並添加+ ),例如300+10*51+20+2*21 ,就可以使用正則表達式。

我有下面的工作代碼:

import re


input_str = '300+10*51+20+2*21'

#input_str = '1*2+3*4'


prod_re = re.compile(r"(\d+)\*(\d+)")
sum_re = re.compile(r"(\d+)\+?")

result = 0
index = 0
while (index <= len(input_str)-1):
    #-----
    prod_match = prod_re.match(input_str, index)
    if prod_match:
        # print 'find prod', prod_match.groups()
        result += int(prod_match.group(1))*int(prod_match.group(2))
        index += len(prod_match.group(0))+1
        continue
    #-----
    sum_match = sum_re.match(input_str, index)
    if sum_match:
        # print 'find sum', sum_match.groups()
        result += int(sum_match.group(1))
        index += len(sum_match.group(0))
        continue
    #-----
    if (not prod_match) and (not sum_match):
        print 'None match, check input string'
        break


print result

我想知道是否有辦法避免在上面創建變量index

該算法似乎不正確。 輸入1*2+3*4不會產生正確的結果。 在解決一個乘法之后您繼續解析一個加法似乎是錯誤的,而在某些情況下,您必須先解析更多的乘法再進行任何加法。

通過對正則表達式和循環進行一些更改,您可以實現所需的目標,如下所示:

import re

input_str = '3+1*2+3*4'

# match terms, which may include multiplications
sum_re = re.compile(r"(\d+(?:\*\d+)*)(?:\+|$)")
# match factors, which can only be numbers 
prod_re = re.compile(r"\d+")

result = 0
# find terms
for sum_match in sum_re.findall(input_str):
    # for each term, determine its value by applying the multiplications
    product = 1
    for prod_match in prod_re.findall(sum_match):
        product *= int(prod_match)
    # add the term's value to the result
    result += product

print (result)

說明

這個正則表達式:

(\d+(?:\*\d+)*)(?:\+|$)

...匹配一個整數,后跟零個或多個乘法:

(?:\*\d+)*

(?:使其成為非捕獲組。沒有?:方法, findall會將匹配的這一部分分配給一個單獨的列表元素,我們不希望這樣。

\\*\\d+是:文字星號后跟數字。

最后一個(?:\\+|$)還是一個非捕獲組,它需要跟在后面的文字+或輸入的末尾( $ )。

解決問題的方法應該是在term前加一個可能的符號,然后是term列表,並用加法運算符分隔,例如

[+-]?({term}([+-]{term})*)

其中每個項是一個因素,其后可能是一個乘法運算符的空列表,而另一個因素是這樣的:

{factor}([*/]{factor})*

其中factor是一個數字序列[0-9]+ ,因此替換為:

[+-]?([0-9]+([*/][0-9]+)*([+-][0-9]+([*/][0-9]+)*)*)

這將是您可能擁有的正則表達式,它假定您可以擁有的運算符之間的優先級結構。 但是,它不允許您提取不同的元素,這很容易證明:正則表達式內部僅包含4個組元素(左括號為4個),因此您只能匹配其中四個(第一個項,第一個項的最后一個因子)項,最后一項以及最后一項的最后一個因子如果開始用括號將子表達式包圍起來,則可以得到更多,但正則表達式中的組數是有限的 ,並且可以構造一個可能無限長的正則表達式。

這樣說(您將無法從正則表達式結構中分離出所有事物)采取了另一種方法:第一個符號是可選的,並且可以跟在后面的未定義數量的術語,由乘法運算符或加法符分隔那些:

[+-]?([0-9]+([*/+-][0-9]+)*

也將起作用(它匹配相同的表達式集。即使您限制只有一個運算符可以插入1個或多個數字的安全性這一事實,結果正則表達式也可以簡化為:

[-+]?[0-9]([*/+-]?[0-9])*

或使用當今常用的符號來:

[-+]?\d([*/+-]?\d)* 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM