在多个括号和不同类型的括号之间解析数据

时间:2015-05-04 22:58:14

标签: python regex parsing

我正在尝试解析位于三种括号内的数据。 {},[]和<>

棘手的部分是数据可以嵌套在多个括号之间。

简单案例:

element-type { a | b | c | d} [ duration ]

这是一个简单的案例,我可以使用正则表达式来抓取{}和[]

之间的东西

这是一个更难的例子

tcp [ udp-mode { off | on { encrypted | plain }}]

我本来想要做的是提取“udp-mode”,然后提取可能的选项和选项选项。我打算将它存储在树形结构中。我正在努力弄清楚如何解析这个?棘手的部分是嵌套{},因为它可以进一步嵌套。

  • [] =可选
  • {} =从以下
  • 中选择一个选项
  • <> =用户输入

如果它的花括号我想要在大括号之前抓住所有内容,直到我点击另一个右括号或字符串的开头。

对于方括号,我想抓住它里面的一切。但同样,它们可以包含大括号或<>

对于<>我想要抓住里面的一切,以及之前的所有内容,直到命中一个括号或字符串

解析此类数据的好方法是什么?

1 个答案:

答案 0 :(得分:1)

以下是使用pyparsing解决您的问题:

from pyparsing import *

LBRACK,RBRACK,LBRACE,RBRACE,LANGLE,RANGLE,VERT_BAR = map(Suppress,"[]{}<>|")

expr = Forward()

ident = Word(alphas, alphanums+'-_')

optional_expr = (LBRACK + expr + RBRACK)
reqd_expr = (LBRACE + expr + RBRACE)
user_expr = (LANGLE + OneOrMore(ident) + RANGLE)

term = ident | optional_expr | reqd_expr | user_expr
term = Group(term * (2,None)) | term

expr <<= OneOrMore(term + ~VERT_BAR | Group(delimitedList(term,VERT_BAR)))


tests = """\
element-type { a | b | c | d} [ duration ]
tcp [ udp-mode { off | on { encrypted | plain }}]""".splitlines()

for t in tests:
    print t
    print expr.parseString(t).asList()[0]
    print

打印:

element-type { a | b | c | d} [ duration ]
['element-type', ['a', 'b', 'c', 'd'], 'duration']

tcp [ udp-mode { off | on { encrypted | plain }}]
['tcp', ['udp-mode', ['off', ['on', ['encrypted', 'plain']]]]]

要了解如何解释不同的分组,我添加了分析时动作来装饰返回的组:

def make_pa(prefix):
    def pa(tokens):
        return ParseResults([prefix] + [tokens])
    return pa

optional_expr = (LBRACK + expr + RBRACK).setParseAction(make_pa("OPT:"))
reqd_expr = (LBRACE + expr + RBRACE).setParseAction(make_pa("REQD:"))
user_expr = (LANGLE + OneOrMore(ident) + RANGLE).setParseAction(make_pa("USER:"))

term = ident | optional_expr | reqd_expr | user_expr
term = Group(term * (2,None)) | term
alternation = Group(term + OneOrMore(VERT_BAR + term))
alternation.setParseAction(make_pa("OR:"))

您的两个测试字符串将返回以下嵌套列表:

element-type { a | b | c | d} [ duration ]
['element-type', 'REQD:', ['OR:', [['a', 'b', 'c', 'd']]], 'OPT:', ['duration']]

tcp [ udp-mode { off | on { encrypted | plain }}]
['tcp', 'OPT:', [['udp-mode', 'REQD:', ['OR:', [['off', ['on', 'REQD:', ['OR:', [['encrypted', 'plain']]]]]]]]]]