Python regexp匹配或标记化

2024-10-04 01:34:13 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个数据结构的转储,我正试图将其转换为XML。结构中有许多嵌套结构。所以我对如何开始有点不知所措,因为我能想到的所有正则表达式都不能在嵌套表达式上工作。在

例如,假设有这样一个结构转储:

abc = (  
        bcd = (efg = 0, ghr = 5, lmn = 10), 
        ghd = 5, 
        zde = (dfs = 10, fge =20, dfg = (sdf = 3, ert = 5), juh = 0))

我想得到这样的输出:

^{pr2}$

那么,什么是解决这个问题的好方法呢?将表达式标记化,使用一个聪明的正则表达式还是使用堆栈?在


Tags: 数据结构表达式xml结构abcdfs正试图dfg
3条回答

我不认为regexp是最好的方法,但是对于那些好奇的人来说,可以这样做:

def expr(m):
    out = []
    for item in m.group(1).split(','):
        a, b = map(str.strip, item.split('='))
        out.append('<%s>%s</%s>' % (a, b, a))
    return '\n'.join(out)

rr = r'\(([^()]*)\)'
while re.search(rr, data):
    data = re.sub(rr, expr, data)

基本上,我们反复用xml块替换最下面的括号(no parens here),直到不再有括号为止。为了简单起见,我还将主表达式包含在括号中,如果不是这样,只需在解析之前执行data='(%s)' % data。在

下面是一个使用pyparsing更符合习惯用法的另一个答案。因为它提供了一个详细的语法来说明可以看到什么输入和应该返回什么结果,所以解析的数据并不是“杂乱无章的”,因此toXML()不需要那么辛苦地工作,也不需要进行任何真正的清理。在

print "\n----- ORIGINAL -----\n"

dump = """
abc = (  
        bcd = (efg = 0, ghr = 5, lmn 10), 
        ghd = 5, 
        zde = (dfs = 10, fge =20, dfg = (sdf = 3, ert = 5), juh = 0))
""".strip()

print dump


print "\n----- PARSED INTO LIST -----\n"

from pyparsing import Word, alphas, nums, Optional, Forward, delimitedList, Group, Suppress

def Syntax():
    """Define grammar and parser."""

    # building blocks
    name   = Word(alphas)
    number = Word(nums)
    _equals = Optional(Suppress('='))
    _lpar   = Suppress('(')
    _rpar   = Suppress(')')

    # larger constructs
    expr = Forward()
    value = number | Group( _lpar + delimitedList(expr) + _rpar )
    expr << name + _equals + value

    return expr

parsed = Syntax().parseString(dump)
print parsed


print "\n----- SERIALIZED INTO XML ----\n"


def toXML(part, level=0):

    xml = ""
    indent = "    " * level
    while part:
        tag     = part.pop(0)
        payload = part.pop(0)

        insides = payload if isinstance(payload, str) \
                          else "\n" + toXML(payload, level+1) + indent

        xml += "{indent}<{tag}>{insides}</{tag}>\n".format(**locals())

    return xml

print toXML(parsed)

输入和XML输出与我的另一个答案相同。parseString()返回的数据是唯一真正的更改:

^{pr2}$

使用pyparsing。在

$ cat parsing.py 
from pyparsing import nestedExpr

abc = """(  
        bcd = (efg = 0, ghr = 5, lmn 10), 
        ghd = 5, 
        zde = (dfs = 10, fge =20, dfg = (sdf = 3, ert = 5), juh = 0))"""
print nestedExpr().parseString(abc).asList()

$ python parsing.py
[['bcd', '=', ['efg', '=', '0,', 'ghr', '=', '5,', 'lmn', '10'], ',', 'ghd', '=', '5,', 'zde', '=', ['dfs', '=', '10,', 'fge', '=20,', 'dfg', '=', ['sdf', '=', '3,', 'ert', '=', '5'], ',', 'juh', '=', '0']]]

相关问题 更多 >