2017-02-09 28 views
0

我有字符串變量,如:字符串轉換爲條件和聲明

s = 'apple<3,meizu>5;samsung=9,foo=bar' 
如字典的

和:

D = [ 
     {'apple': 9, 'meizu': 12, 'samsung': 90, 'oppo': 12', foo': 'bar'}, 
     {'apple': 91, 'meizu': 22, 'samsung': 72, 'foo': 'test'}, 
     ... 
    ] 

我需要s轉換爲

"if apple < 3 and (meizu > 5 or samsung==9) and foo=='bar'" # (semicolon is OR, comma is AND) 

和檢查列表D中的每個元素都具有此條件,如:

for i in D: 
    if i['apple']<3 and (i['meizu']>5 or i['samsung']==9) and i['foo']=='bar': 
    print ('ok') 

我不明白如何實現它。我試過eval(s),但我不確定這是一個好的解決方案。

+0

那麼,'or'在這個表示法中的結合性強於'和'嗎?除了這一點,其他的一切都應該可以通過簡單的字符串替換輕鬆實現。 –

+0

是的,我需要像這樣的例子轉換分號和逗號:如果你結合OR和與運算符,OR運算符將優先 – SmartSt

+0

@tobias_k,但在我的鍵,我感興趣的概念問題,如何轉換字符串到Python代碼 – SmartSt

回答

0

你可以通過一些字符串替換來實現這一目標:

  • 取代"=""=="(小心,如​​果你也有<=>=
  • d['x']更換名稱x;你可以使用re.sub有回調這個
  • and;or

棘手的部分是讓or綁定比and更強的替代,,但是你可以通過周圍的一切and引入括號實現這一目標操作員(以及字符串的開始和結尾處),但不在or附近。 (如果字符串已經包含括號這可能會失敗,但我認爲這是某種不帶括號規範化形式的。)

import re 
def to_code(string): 
    code = "(" + string + ")" 
    code = re.sub("[a-z]+", lambda m: "d['%s']" % m.group(0), code) 
    code = code.replace(",", ") and (") 
    code = code.replace(";", " or ") 
    code = code.replace("=", "==") 
    return code 

s = 'apple<3,meizu>5;samsung=9,foo=bar' 
code = to_code(s) 
# (d['apple']<3) and (d['meizu']>5 or d['samsung']==9) and (d['foo']==d['bar']) 

然後,您可以用evald不同詞典的字符串。

D = [{'apple': 2, 'meizu': 12, 'samsung': 9, 'oppo': 12, 'foo': 42, 'bar': 42}, 
    {'apple': 91, 'meizu': 22, 'samsung': 72, 'foo': 'test', 'bar': "blub"}] 

for d in D: 
    print(eval(code)) # prints True, False 
+0

謝謝您的解決方案!關於** eval **方法 - 您如何看待,多少是安全的解決方案?我的意思是,是否過濾輸入字符串應該是? – SmartSt

+0

'eval'總是帶有一定的風險,這取決於要評估的字符串來自何處。然而,在這種情況下,我會認爲它是相對安全的,特別是如果所有的標識符都包含在'd ['...']'中,這應該可以防止大多數嘗試注入惡意代碼。 –