Python正则表达式匹配或标记化

Python正则表达式匹配或标记化,python,regex,tokenize,Python,Regex,Tokenize,我有一个数据结构的转储,我正试图将其转换为XML。结构中有许多嵌套结构。所以我对如何开始有些迷茫,因为我能想到的所有正则表达式都不能在嵌套表达式上工作 例如,假设有这样一个结构转储: abc = ( bcd = (efg = 0, ghr = 5, lmn = 10), ghd = 5, zde = (dfs = 10, fge =20, dfg = (sdf = 3, ert = 5), juh = 0)) 我想得出这样的结果: <

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

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

abc = (  
        bcd = (efg = 0, ghr = 5, lmn = 10), 
        ghd = 5, 
        zde = (dfs = 10, fge =20, dfg = (sdf = 3, ert = 5), juh = 0))
我想得出这样的结果:

< abc >
  < bcd >   
    < efg >0< /efg >  
    < ghr >5< /ghr >  
    < lmn >10< /lmn >  
  < /bcd >  
.....  
< /abc > 
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)


0
5
10

.....  

那么,什么才是解决这个问题的好方法呢?标记表达式、智能正则表达式或使用堆栈?

使用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']]]
使用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']]]

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

< abc >
  < bcd >   
    < efg >0< /efg >  
    < ghr >5< /ghr >  
    < lmn >10< /lmn >  
  < /bcd >  
.....  
< /abc > 
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)
def expr(m):
out=[]
对于m.group(1)中的项目。拆分(','):
a、 b=映射(str.strip,item.split('='))
out.append(“%s%”(a,b,a))
返回'\n'。加入(退出)
rr=r'\([^()]*)\)
重新搜索时(rr,数据):
data=re.sub(rr、expr、data)

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

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

< abc >
  < bcd >   
    < efg >0< /efg >  
    < ghr >5< /ghr >  
    < lmn >10< /lmn >  
  < /bcd >  
.....  
< /abc > 
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)
def expr(m):
out=[]
对于m.group(1)中的项目。拆分(','):
a、 b=映射(str.strip,item.split('='))
out.append(“%s%”(a,b,a))
返回'\n'。加入(退出)
rr=r'\([^()]*)\)
重新搜索时(rr,数据):
data=re.sub(rr、expr、data)
基本上,我们反复使用xml块替换最下面的括号
(这里没有括号)
,直到没有更多的括号为止。为简单起见,我还将主表达式包含在括号中,如果不是这样,在解析之前只需执行
data='(%s)%data

我喜欢Igor Chubin的“use pyparsing”答案,因为一般来说,regexp处理嵌套结构的能力非常差(尽管thg435的迭代替换解决方案是一个巧妙的解决方案)

但是一旦pyparsing完成了它的工作,您就需要一个例程来遍历列表并发出XML。它需要对pyparsing结果的不完善性保持智能。例如,
fge=20,
不会产生您想要的
['fge','=','20']
,而是
['fge','=20',]
。逗号有时也会添加在没有帮助的地方。我是这样做的:

from pyparsing import nestedExpr

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

dump = dump.strip()

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

wrapped = dump if dump.startswith('(') else "({})".format(dump)
parsed = nestedExpr().parseString(wrapped).asList()

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

def toXML(part, level=0):

    def grab_tag():
        return part.pop(0).lstrip(",")

    def grab_payload():
        payload = part.pop(0)
        if isinstance(payload, str):
            payload = payload.lstrip("=").rstrip(",")
        return payload

    xml = ""
    indent = "    " * level
    while part:
        tag     = grab_tag() or grab_tag()
        payload = grab_payload() or grab_payload()
        # grab twice, possibly, if '=' or ',' is in the way of what you're grabbing

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

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

    return xml

print "\n----- SERIALIZED INTO XML ----\n"
print toXML(parsed[0])
从pyparsing导入nestedExpr
dump=“”
abc=(
bcd=(efg=0,ghr=5,lmn 10),
ghd=5,
zde=(dfs=10,fge=20,dfg=(sdf=3,ert=5,juh=0))
"""
dump=dump.strip()
打印“\n-----原件------\n”
打印转储
wrapped=dump if dump.startswith(“(”)else“({})”.format(dump)
parsed=nestedExpr().parseString(已包装).asList()
打印“\n------已解析为列表------\n”
打印解析
def toXML(部件,级别=0):
def抓取标签():
返回部分.pop(0).lstrip(“,”)
def抓斗_有效负载():
有效载荷=零件。pop(0)
如果isinstance(有效载荷,str):
有效载荷=有效载荷.lstrip(“=”).rstrip(“,”)
返回有效载荷
xml=“”
缩进=“级别”
虽然部分:
tag=grab_tag()或grab_tag()
有效载荷=抓取有效载荷()或抓取有效载荷()
#如果“=”或“,”妨碍了您抓取的内容,则可能抓取两次
内部=存在时的有效载荷(有效载荷,str)\
else“\n”+toXML(有效载荷,级别+1)+缩进
xml+=“{indent}{insides}\n”。格式(**locals())
返回xml
打印“\n-----序列化为XML----\n”
打印toXML(已解析[0])
导致:

----- ORIGINAL -----

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

----- PARSED INTO LIST -----

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

----- SERIALIZED INTO XML ----

<abc>
    <bcd>
        <efg>0</efg>
        <ghr>5</ghr>
        <lmn>10</lmn>
    </bcd>
    <ghd>5</ghd>
    <zde>
        <dfs>10</dfs>
        <fge>20</fge>
        <dfg>
            <sdf>3</sdf>
            <ert>5</ert>
        </dfg>
        <juh>0</juh>
    </zde>
</abc>
——原件-----
abc=(
bcd=(efg=0,ghr=5,lmn 10),
ghd=5,
zde=(dfs=10,fge=20,dfg=(sdf=3,ert=5,juh=0))
-----解析为列表-----
[['abc'、'='、['bcd'、'='、['efg'、'='、'0'、'ghr'、'='、'5'、'lmn'、'10']、'、'ghd'、'='、'5'、'zde'、'='、['dfs'、'10'、'fge'、'20'、'dfg'、'sdf'、'sdf'、'3'、'ert'、'='、'5'、'5'、'zde'、'juh'、'0']
-----序列化为XML----
0
5.
10
5.
10
20
3.
5.
0
我喜欢Igor Chubin的“使用pyparsing”答案,因为一般来说,regexp处理嵌套结构的能力非常差(尽管thg435的迭代替换解决方案是一个聪明的解决方案)

但是一旦pyparsing完成了它的工作,您就需要一个例程来遍历列表并发出XML。它需要对pyparsing结果的不完善性保持智能。例如,
fge=20,
不会产生您想要的
['fge','=','20']
但是
['fge','20']
。有时在没有帮助的地方也会添加逗号。我是这样做的:

from pyparsing import nestedExpr

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

dump = dump.strip()

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

wrapped = dump if dump.startswith('(') else "({})".format(dump)
parsed = nestedExpr().parseString(wrapped).asList()

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

def toXML(part, level=0):

    def grab_tag():
        return part.pop(0).lstrip(",")

    def grab_payload():
        payload = part.pop(0)
        if isinstance(payload, str):
            payload = payload.lstrip("=").rstrip(",")
        return payload

    xml = ""
    indent = "    " * level
    while part:
        tag     = grab_tag() or grab_tag()
        payload = grab_payload() or grab_payload()
        # grab twice, possibly, if '=' or ',' is in the way of what you're grabbing

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

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

    return xml

print "\n----- SERIALIZED INTO XML ----\n"
print toXML(parsed[0])
从pyparsing导入nestedExpr
dump=“”
abc=(
bcd=(efg=0,ghr=5,lmn 10),
ghd=5,
zde=(dfs=10,fge=20,dfg=(sdf=3,ert=5,juh=0))
"""
dump=dump.strip()
打印“\n-----原件------\n”
打印转储
wrapped=dump if dump.startswith(“(”)else“({})”.format(dump)
parsed=nestedExpr().parseString(已包装).asList()
打印“\n------已解析为列表------\n”
打印解析
def toXML(部件,级别=0):
def抓取标签():
返回部分.pop(0).lstrip(“,”)
def抓斗_有效负载():
有效载荷=零件。pop(0)
如果isinstance(有效载荷,str):
有效载荷=有效载荷.lstrip(“=”).rstrip(“,”)
返回有效载荷
xml=“”
缩进=“级别”
虽然部分:
tag=grab_tag()或grab_tag()
有效载荷=抓取有效载荷()或抓取有效载荷()
#如果“=”或“,”妨碍了您抓取的内容,则可能抓取两次
内部=存在时的有效载荷(有效载荷,str)\