首页 > 解决方案 > 替换字符串中的某些未知单词

问题描述

我正在寻找一种更优雅的解决方案来替换字符串中的一些前期未知单词,not除了andor

仅作为下面的示例,但可以是任何东西,但总是可以用 eval() 评估)

输入:(DEFINE_A or not(DEFINE_B and not (DEFINE_C))) and DEFINE_A

输出:(self.DEFINE_A or not(self.DEFINE_B and not (self.DEFINE_C))) and self.DEFINE_A

我创建了一个解决方案,但它看起来有点奇怪。有没有更干净的方法?

s = '(DEFINE_A or not(DEFINE_B and not (DEFINE_C))) and DEFINE_A'
words = re.findall(r'[\w]+|[()]*|[ ]*', s)
for index, word in enumerate(words):
    w = re.findall('^[a-zA-Z_]+$', word)
    if w and w[0] not in ['and','or','not']:
        z = 'self.' + w[0]
        words[index] = z
new = ''.join(str(x) for x in words)
print(new)

将正确打印:

(self.DEFINE_A or not(self.DEFINE_B and not (self.DEFINE_C))) and self.DEFINE_A

标签: python

解决方案


首先,您可以使用简单的\w+. 然后,使用负前瞻,您可以排除您不想要的那些。现在剩下要做的就是re.sub直接使用该模式:

s = '(DEFINE_A or not(DEFINE_B and not (DEFINE_C))) and DEFINE_A'

new = re.sub(r"(?!and|not|or)\b(\w+)", r"self.\1", s)

print(new)

这将给出:

(self.DEFINE_A or not(self.DEFINE_B and not (self.DEFINE_C))) and self.DEFINE_A

您可以在此处测试并查看此正则表达式的工作原理。


如果您的“变量”的名称总是大写,这会稍微简化模式并使其更有效率。只需使用:

new = re.sub(r"([A-Z\d_]+)", r"self.\1", s)

这不仅是一个更简单的模式(为了可读性),而且效率更高。在这个例子中,与原来的 196 步相比,它只需要 70 步(可以在链接的右上角看到)。

您可以在此处查看新模式的实际应用。


推荐阅读