您可以使用解析器。
这显然不是一个简单的解决方法,但如果您已经熟悉解析,那么绝对可以在这里应用它。
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, TEXT( })
ORDEREDDICT 令牌由第一条规则处理,因此变为:
data({'key': ), (我们期望这里有数据) ORDEREDDICT, LPAREN, (我们在这里, 寻找数据然后 RPAREN) TEXT([), LPAREN, TEXT('abc', 1), RPAREN, TEXT (])、RPAREN、文本(})
然后,根据第四条规则将 TEXT([) 识别为数据:
data({'key': ), (我们期望这里有数据) ORDEREDDICT, LPAREN, (我们在这里, 寻找数据然后 RPAREN) data([), LPAREN, TEXT('abc', 1), RPAREN, TEXT (])、RPAREN、文本(})
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) 数据('abc', 1), RPAREN, TEXT(]), RPAREN, TEXT(})
我们有我们正在寻找的 data+RPAREN 序列,所以我们可以用第二条规则来总结它:
data({'key': ), (我们在这里期待数据) ORDEREDDICT, LPAREN, (我们在这里期待数据然后是 RPAREN) data([), (我们在这里, 我们在这里期待数据) data(('abc', 1)), TEXT(]), RPAREN, TEXT(})
现在我们有了应用第三条规则的数据:
data({'key': ), (我们期望这里有数据) ORDEREDDICT, LPAREN, (我们在这里,我们期望有数据,然后这里是 RPAREN) data([('abc', 1)), TEXT(]), RPAREN , 文本(})
我们还不能应用第一条规则。你应该明白了,所以我从现在开始写步骤:
data({'key': ), (我们在这里期待数据) ORDEREDDICT, LPAREN, (我们期待数据然后在这里 RPAREN) data([('abc', 1)), (我们在这里,寻找数据) TEXT (])、RPAREN、文本(})
data({'key': ), (我们在这里期待数据) ORDEREDDICT, LPAREN, (我们期待数据然后在这里 RPAREN) data([('abc', 1)), (我们在这里, 寻找数据) data (])、RPAREN、文本(})
data({'key': ), (我们期望这里有数据) ORDEREDDICT, LPAREN, (我们在这里,我们期望数据然后这里是 RPAREN) data([('abc', 1)]), RPAREN, TEXT(} )
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)