您可以使用解析器。
这显然不是一个简单的解决方案,但如果您已经熟悉解析,则绝对可以在这里应用。
现有的 Python 解析器有很多不同的,例如,假设您选择 PLY(不是最好的,但考虑到您想要做的就足够了)
解析首先需要对文本进行标记。在这里你只需要几个令牌:
import ply.lex as lex
tokens = (LPAREN, RPAREN, ORDEREDDICT, TEXT)
t_LPAREN = "("
t_RPAREN = ")"
t_ORDEREDDICT = "OrderedDict"
t_TEXT = r'(?:(?!(OrderedDict|\(|\))).)+'
lexer = lex.lex()
这意味着解析器将认为“(”符号是“LPAREN”(左括号),“)”符号是“RPAREN”,而序列“OrderedDict”是一个特殊的东西。其他符号序列(不包含括号或“OrderedDict”序列)将被视为 TEXT。
例如,"{'key': OrderedDict([('abc', 1)])}" 此时将转换为:
TEXT({'key': ), ORDEREDDICT, LPAREN, TEXT([), LPAREN, TEXT('abc', 1), RPAREN, TEXT(]), RPAREN, TEXT(})
您可以使用以下方法对其进行测试:
lexer.input("{'key': OrderedDict([('abc', 1)])}")
然后可以进行实际的解析:
import ply.yacc as yacc
import json
def p_ordereddict(p):
'data : ORDEREDDICT LPAREN data RPAREN'
p[0] = json.dumps(OrderedDict(json.loads(p[3])))
def p_otherparenthesis(p):
'data : LPAREN data RPAREN'
p[0] = p[1]+p[2]+p[3]
def p_concat(p):
'data : data data'
p[0] = p[1]+p[2]
def p_texttodata(p):
'data : TEXT'
p[0] = p[1]
parser = yacc.yacc()
这应该被理解为三个规则:
- 如果我看到“ORDEREDDICT”标记,我必须在其后查找左括号,然后是称为“数据”的内容,然后是右右括号。然后将整个事物本身视为“数据”,其值是我们在括号之间但通过“OrderedDict”运算符传递的数据之一。
- 如果我看到一个左括号(而我不是在前一种情况下),我需要识别一个“数据”序列和一个右右括号。整个事情本身就是数据。
- 如果我看到多个数据彼此相邻,我可以将它们连接起来
- 标记为 TEXT 的内容是数据
收回我们之前的例子:
"{'key': OrderedDict([('abc', 1)])}"
被转换为:
TEXT({'key': ), ORDEREDDICT, LPAREN, TEXT([), LPAREN, TEXT('abc', 1), RPAREN, TEXT(]), RPAREN, TEXT(})
解析器从左边开始,找到一个 TEXT 标记。唯一关心前导 TEXT 令牌的规则是第 4 条,根据这条规则,令牌变成数据:
data({'key': ), ORDEREDDICT, LPAREN, TEXT([), LPAREN, TEXT('abc', 1), RPAREN, TEXT(]), RPAREN, TEXT(})
现在我们有了一个领先的数据对象。定义应该发生什么的规则是第三条:我们必须进一步寻找其他数据对象:
data({'key': ), (我们现在在这里,寻找数据) ORDEREDDICT, LPAREN, TEXT([), LPAREN, TEXT('abc', 1), RPAREN, TEXT(]), RPAREN , 文本(})
ORDEREDDICT 令牌由第一条规则处理,因此变为:
data({'key': ), (我们期望这里有数据) ORDEREDDICT, LPAREN, (我们在这里, 寻找数据然后RPAREN) TEXT([), LPAREN, TEXT('abc', 1), RPAREN, TEXT(]), RPAREN, TEXT(})
然后,根据第 4 条规则将 TEXT([) 识别为数据:
data({'key': ), (我们期望这里有数据) ORDEREDDICT, LPAREN, (我们在这里, 寻找数据然后RPAREN) data([), LPAREN, TEXT('abc', 1), RPAREN, TEXT(]), RPAREN, TEXT(})
data([) 后面的不是 RPAREN,但这不是问题,因为第三条规则意味着可以连接一系列数据对象:
data({'key': ), (我们在这里期待数据) ORDEREDDICT, LPAREN, (我们期待数据然后在这里 RPAREN) data([), (我们在这里, 寻找数据) LPAREN, TEXT(' abc', 1), RPAREN, TEXT(]), RPAREN, TEXT(})
第二条规则适用:
data({'key': ), (我们在这里期待数据) ORDEREDDICT, LPAREN, (我们在这里期待数据然后是 RPAREN) data([), (我们在这里期待数据) LPAREN, (我们在这里, 寻找对于数据,然后是 RPAREN) TEXT('abc', 1), RPAREN, TEXT(]), RPAREN, TEXT(})
第四条规则:
data({'key': ), (我们在这里期待数据) ORDEREDDICT, LPAREN, (我们在这里期待数据然后是 RPAREN) data([), (我们在这里期待数据) LPAREN, (我们在这里, 寻找对于数据,然后是 RPAREN) data('abc', 1), RPAREN, TEXT(]), RPAREN, TEXT(})
我们有我们正在寻找的数据+RPAREN 序列,所以我们可以用第二条规则来总结它:
data({'key': ), (我们在这里期待数据) ORDEREDDICT, LPAREN, (我们期待数据然后在这里 RPAREN) data([), (我们在这里, 我们期待数据) data((' abc', 1)), TEXT(]), RPAREN, TEXT(})
现在我们有了应用第三条规则的数据:
data({'key': ), (我们在这里期待数据) ORDEREDDICT, LPAREN, (我们在这里, 我们期待数据然后在这里 RPAREN) data([('abc', 1)), TEXT(] ), RPAREN, TEXT(})
我们还不能应用第一条规则。你应该明白了,所以我从现在开始写步骤:
data({'key': ), (我们在这里期待数据) ORDEREDDICT, LPAREN, (我们期待数据然后在这里 RPAREN) data([('abc', 1)), (我们在这里, 寻找数据)TEXT(]),RPAREN,TEXT(})
data({'key': ), (我们在这里期待数据) ORDEREDDICT, LPAREN, (我们期待数据然后在这里 RPAREN) data([('abc', 1)), (我们在这里, 寻找数据)数据(]),RPAREN,文本(})
data({'key': ), (我们在这里期待数据) ORDEREDDICT, LPAREN, (我们在这里, 我们期待数据然后在这里 RPAREN) data([('abc', 1)]), RPAREN,文本(})
data({'key': ), (我们在这里,我们期望这里有数据) data({'abc':1}), TEXT(})
(我们在这里)data({'key': {'abc':1}), TEXT(})
data({'key': {'abc':1}),(我们在这里,寻找数据)TEXT(})
data({'key': {'abc':1}),(我们在这里,寻找数据)data(})
数据({'key': {'abc':1}})
最后,要使用您的解析器,只需调用它的“parse”方法。例如:
example = "{'key': OrderedDict([('abc', 1)])}"
parsed = parser.parse(example, lexer=lexer)
print(parsed)