在Python中处理包含括号的字符串

问题描述

我有一个这样的字符串,

"(a=1) and ((b=2) or (c=3))"

哪里有“和” ,我需要在python中将其转换为此,

"query[(a=1)].add(query[(b=2) or (c=3)])"

您可以看到发生了两件事,
每当我做 add 时,我都会用query []包装操作数,然后将a and b转换为a.add(b)

如果字符串是类似的另一个示例,

"(a=1) and ((b=2) and (c=3))",其中有两个和。

结果应该是

"query[(a=1)].add(query[(b=2)].add(query[(c=3)]))"

我不能对此进行硬编码,因为括号可以是任何嵌套级别。

我上面显示的表达式是简化的解释,也可能是这样,

'((Attributes.name=="usertype") & (cast(User_Values.value,db.String())=='"Employee"')) and (((Attributes.name=="emails") & (User_Values.value.contains([{"type":"examplecom"}]))) or ((Attributes.name=="emails") & (User_Values.value.contains([{"value":"exampleorg"}]))))'

进步:-

试图使用“ pyparsing”库获取操作数的外括号内容

ms = '((Attributes.name=="usertype") & (cast(User_Values.value,db.String())=='"Employee"')) and (((Attributes.name=="emails") & (User_Values.value.contains([{"type":"examplecom"}]))) and ((Attributes.name=="emails") & (User_Values.value.contains([{"value":"exampleorg"}]))))'

scanner = originalTextFor(nestedExpr('(',')'))

for match in scanner.searchString(ms):
    print("match is ..........",match[0])

明白了

((Attributes.name=="usertype") & (cast(User_Values.value,db.String())==Employee))
(((Attributes.name=="emails") & (User_Values.value.contains([{"type":"examplecom"}]))) and ((Attributes.name=="emails") & (User_Values.value.contains([{"value":"exampleorg"}]))))

接下来,我正在寻找操作数的最外括号内容。 在上面的示例中没有发生这种情况。它仅给出两个独立的括号内容

于2020年10月8日编辑

Ken T的解决方案很有意义,但是我注意到那里存在一个问题。

"((b=2) and (c=3)) and (a=1)",其中有两个和。

结果应该是

"query[(b=2)].add(query[(c=3)]).add(query[(a=1)])" 但结果是,

query[((b=2)].add(query[c=3)) and (a=1])

示例

输入

'(((Values.attribute=="1") & (cast(Values.value,db.String()).like('"%a%"'))) and ((Values.attribute=="3") & (cast(Values.value,db.String()).like('"%b%"')))) and ((Values.attribute=="1") & (cast(Values.value,db.String()).like('"%a%"')))'

预期输出

query[((Values.attribute=="1") & (cast(Values.value,db.String()).like(%a%)))]
.add(query[(Values.attribute=="3") & (cast(Values.value,db.String()).like(%b%))])
.add(query[(Values.attribute=="1") & (cast(Values.value,db.String()).like(%a%)]))

但实际输出

query[(((Values.attribute=="1") & (cast(Values.value,db.String()).like(%b%))))]
.add(query[(Values.attribute=="1") & (cast(Values.value,db.String()).like(%a%)]))

遵守括号。

不得在query []

中包含和.add()

我该如何纠正Ken T的解决方案。

解决方法

递归!这是一个递归问题。

import re

def queryGen(text,lastOP=''):
    pattern = re.compile("\((.+?)\)\s+(and|or)+\s\((.+)\)")
    res = pattern.search(text)
    
    if not res:
        if lastOP == 'or':
            return text
        elif lastOP == 'and':
            return f'query[{text}]'


    if res.group(2)=='and':
        return f"query[({res.group(1)})].add({queryGen(res.group(3),lastOP='and')})"
    if res.group(2)=='or':
        return f"query[({res.group(1)}) or ({queryGen(res.group(3),lastOP='or')})]"

        
        

print(queryGen("(a=1) and ((b=2) or (c=3))"))
print(queryGen("(a=1) and ((b=2) and (c=3))"))
print(queryGen("""((Attributes.name=="usertype") & (cast(User_Values.value,db.String())=='"Employee"')) and (((Attributes.name=="emails") & (User_Values.value.contains([{"type":"examplecom"}]))) or ((Attributes.name=="emails") & (User_Values.value.contains([{"value":"exampleorg"}]))))"""))

返回:

query[(a=1)].add(query[(b=2) or (c=3)])
query[(a=1)].add(query[(b=2)].add(query[c=3]))
query[((Attributes.name=="usertype") & (cast(User_Values.value,db.String())=='"Employee"'))].add(query[((Attributes.name=="emails") & (User_Values.value.contains([{"type":"examplecom"}]))) or ((Attributes.name=="emails") & (User_Values.value.contains([{"value":"exampleorg"}])))])

您可以在以下网站上交互式测试正则表达式模式:

https://regex101.com/r/C1GFuS/1