2016-03-12 27 views
1

給定一組字符串這樣返回的每個元素:60=60100=60+30+10200=120+50+30300=200+100180=60+50+40+20+10我需要一個正則表達式解析(和驗證),這些字符串。比賽應該是嚴格的(例如,號碼和運營商之間不允許有空格)。的Python:捕獲和量詞

我結束了正則表達式像(\d+)=(\d+)(?:\+(\d+))*

它匹配他們都完美,但提取的比賽與re.match(regex, string).groups()回報('100', '60', '10')('200', '120', '30'),...

見,*量詞匹配的只有最後一個數字!這是預期的,但並不能解決我的問題。

*量詞分開返回所有匹配的最pythonic方法是什麼?因此,我可以輕鬆地將各個位單獨匹配,存儲最後的匹配位置並從該位置繼續解析,但它看起來有點難看。

+0

是否有總有兩個'+'經營者? – gtlambert

+0

不,我會添加更多示例 – dmzkrsk

+0

查看我的帖子。您可以很容易地評估+ - 和十進制數字。 – Saleem

回答

1

如果+是您可以得到的唯一運算符(正如我從您提到sum()這一事實中假設的那樣),則不需要正則表達式。只要使用正規.split()

total, expression = string.split("=") 
assert int(total.strip()) == sum(int(x.strip()) for x in expression.split("+")) 
+0

它將匹配字符串與空格'100 = 50 + 30 + 20',但它們應該失敗 – dmzkrsk

+0

@dmzkrsk:好的。我加了'.strip()' – zondo

+0

等一下。你是否希望它失敗?它會有我的方式,但現在我改變了它,我不知道這是你想要的。 – zondo

3

並且怎麼樣不使用正則表達式,但使用解析器呢?

from pyparsing import * 

integer = Word(nums).setParseAction(lambda t:int(t[0])) 
variable = Word(alphas,exact=1) 
operand = integer | variable 

expop = Literal('^') 
signop = oneOf('+ -') 
multop = oneOf('* /') 
plusop = oneOf('+ -') 
factop = Literal('!') 
equalop = Literal('=') 

expr = operatorPrecedence(operand, 
    [("=", 2, opAssoc.LEFT), 
    ("+", 2, opAssoc.RIGHT),] 
    ) 


test=['60=60', '70=10+20', '100=1+2+42+67'] 

for t in test: 
    print t, u'→', expr.parseString(t) 
    print 

這將隨後輸出:

60=60 → [[60, '=', 60]] 

70=10+20 → [[[70, '=', 10], '+', 20]] 

100=1+2+42+67 → [[[100, '=', 1], '+', [2, '+', [42, '+', 67]]]] 

然後拿到整數,你只需要扁平化樹,查找所有整數。


的另一種方式,我覺得稍顯不足優雅,不做字符串的語法檢查,將拆就+=字符串:

for t in test: 
    head, tail = t.split('=') 
    values = [head] + tail.split('+') 
    print t, u'→', values 

這給:

60=60 → ['60', '60'] 
70=10+20 → ['70', '10', '20'] 
100=1+2+42+67 → ['100', '1', '2', '42', '67'] 

最後,我們可以嘗試找到一個正則表達式的魔彈來回答你的問題,但說實話,這不會是我解決這個問題的方法。


N.B:扁平化的列表,這裏有一個辦法:

def flatten(seq): 
    res = [] 
    for item in seq: 
     if (isinstance(item, (tuple, list))): 
      res.extend(flatten(item)) 
     else: 
      res.append(item) 
    return res 
0

嘗試蟒蛇內置功能eval,以評估在運行時的表現。我已經改變了一點正則表達式。它是通用的,可以很容易地用於任何數學運算。

import re 

data = "100=60+30+10, 200=120+50+30, 300=200+100, 180=60+50+40+20+10" 

rx = r"(\d+)=([^, ]+)" 

for res in re.finditer(rx, data, re.IGNORECASE | re.MULTILINE): 
    lhs = eval(res.group(1)) 
    rhs = eval(res.group(2)) 
    assert lhs == rhs 

如果你想一些有趣的代碼段,替換正則表達式:

rx = r"([+-]?\d+(?:\.\d+))=([^, ]+)" 

現在你可以評估正,負,整數和小數了。

0

這似乎很容易解決使用正則表達式(Python的2.7):

>>> import re 
>>> strs = '60=60, 100=60+30+10, 200=120+50+30, 300=200+100, 180=60+50+40+20+10' 
>>> pattern = '((?:\d+)(?:|\+)|(?=|\+)(?:\d+))' 
>>> [re.findall(pattern, str) for str in strs.split(',')] 
[['60', '60'], ['100', '60', '30', '10'], ['200', '120', '50', '30'], ['300', '200', '100'], ['180', '60', '50', '40', '20', '10']] 

REGEX DEMO.