在字符串列表,从值替换变量名和避免重复内容替换(replacing variable names i

2019-10-16 23:52发布

鉴于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!

Answer 1:

要更换VAR1一起离开VAR1::VALUE_X你可以使用负前瞻:

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

一个更强大的解决方案将字符串解析成AST和eval它。



Answer 2:

它看起来(我)这样可以用字符串格式化更容易做到 - 假设你在输入字符串稍微控制:

>>> 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)


文章来源: replacing variable names in string with values from list and avoiding redundant replaces