1

evalの方程式が与えられます:

    eval_str = 'VAR1 > 0 and VAR1 < 10 and (VAR2 == VAR1::VALUE_X or VAR2 == VAR2::VALUE_X)'

タスク:変数(この例ではVAR1、VAR2)を実際の値に置き換え、指定された「定数」(VAR1 :: VALUE_X)を引用符で囲む必要があります。

問題:変数名が定数とeval文字列に存在し、変数が変数名自体を含む文字列に置き換えられる可能性があるため、定数値の変数名が別の定数に置き換えられるという問題が発生しますまたは変数値。よりよく示されています...

     eval_str = '(VAR2 == VAR2::VALUE_X or VAR2 != VAR2::VALUE_Z) and (VAR1 > 0 and VAR1 < 10)'
     var_dict = {'VAR1':'5','VAR2':'VAR1::VALUE_Y'}

     # what I do is strip out most of the special characters
     # the following findall = ['VAR1', '0', 'and', 'VAR1', '10', 'and', 'VAR2', 'VAR1::VALUE_X', 'or', 'VAR2', 'VAR2::VALUE_X']
     for x in re.findall('[^\s()<>=!]+',eval_str):
        # skip digits, and, or, None *need to improve regex
        if x.replace('.','').isdigit() or x == 'and' or x == 'or' or x == 'None':
           continue
        # if variable is in dict
        if x in var_dict.keys():
           # only replace first
           eval_str = eval_str.replace(x,var_dict[x],1) 
        # if is constant
        elif x.__contains__('::'):
           eval_str = eval_str.replace(x,'\'%s\''%x,1)

     print eval_str
     # (5::VALUE_Y == '5::VALUE_Y::VALUE_X' or VAR2 != 'VAR2::VALUE_Z') and (VAR1 > 0 and VAR1 < 10)

各変数/値をインクリメントする代わりに、それぞれに正規表現を使用してすべてを置き換える方がよいでしょうか?または、各置換後に文字列内の自分の位置を記憶する方法があれば、既存のソリューションを修正できますか?

TYVM!

4

2 に答える 2

1

(私には)これは文字列のフォーマットを使用するとはるかに簡単に実行できるように見えます-入力文字列を少し制御できると仮定します:

>>> d={'action':'bar','verb':'foo'}
>>> print ("don't %(action)s a %(verb)s"%d)

またはこれはどうですか:

import re
class DictFormatter(dict):
    def __missing__(self,k):
        return k

eval_str = '(VAR2 == VAR2::VALUE_X or VAR2 != VAR2::VALUE_Z) and (VAR1 > 0 and VAR1 < 10)'
var_dict = DictFormatter()
var_dict.update({'VAR1':'5','VAR2':'VAR1::VALUE_Y'})

extra_space = re.compile(r'[\w:]+')  #words are alphanumeric + ':' + '_'.
eval_str = extra_space.sub(lambda m: ' %s '%(m.group()),eval_str) #make sure there is space between "words"
eval_list = [var_dict[item] for item in eval_str.split()]

print " ".join(eval_list)
于 2012-07-10T13:26:08.687 に答える
0

VAR1残していく代わりに、VAR1::VALUE_Xネガティブルックアヘッドを使用できます。

string = re.sub(r'VAR\d(?!\:\:)', lambda m: var_dict[m.group(0)], string)

より堅牢なソリューションは、文字列をASTに解析して評価します。

于 2012-07-10T13:19:51.750 に答える