正则表达帮助

时间:2011-04-07 13:34:07

标签: python regex

所以我有一个这样的字符串:

A!
B!
C!
<tag>
D!
E!
</tag>
F!
<tag>
G!
</tag>

是否可以用正则表达式解析它,所以我得到这个输出(列表):

[A, B, C, [D, E], F, [G]]

基本上我正在寻找一种方法来分割字符串标记 ...并且标记部分可以在任何地方发生......并且多个时间(但递归...意味着标签内的标签......这不会发生)。整个事情似乎是正常的...这是否可以与正则表达式一起使用?

编辑:我正在使用Python

EDIT2:我只使用A,B,C ......作为表示......这些可以是由字母和数字组成的任何字符串

6 个答案:

答案 0 :(得分:1)

我不知道Python,但你可以用三个简单的正则表达式替换(可能只作为一个正则表达式,但以下应该可以正常工作)。

Javascript版本:

str = '[' + str.replace(/!\n/, ', ').replace(/<[^\/>]*>/, '[').replace(/<\/[^>]*>/, ']') + ']';

希望这可以理解为足以翻译成Python。

编辑:您在寻找阵列输出吗?我认为你的示例输出是一个文字字符串,但现在我认为这意味着代表一个嵌套数组。

答案 1 :(得分:1)

<tag> [</tag>替换为],将!\n替换为,,并不容易最后在另外一对[]中包含所有内容?

答案 2 :(得分:0)

是的,这是可能的。

要生成一个平面阵列,你的正则表达式将非常多毛,涉及回溯。它与用于分割CSV文件同时允许引用字符串的正则表达式非常类似,其中<tag> / </tag>标记代替引号,!取代逗号。

但是你要求一个嵌套的数组结构,实际上这会让事情变得更容易。

为了获得嵌套数组结构,您需要执行两个单独的拆分操作,这意味着要执行两个单独的正则表达式操作。您可以按照上面的描述执行第一个操作,但实际上,必须执行两个单独的操作实际上会使您更容易,因为您可以在第一个过程中拆分<tag>中嵌入的部分,并且因为您假设没有嵌套标签,这意味着您不需要进行任何复杂的正则表达式反向跟踪。

希望有所帮助。

答案 3 :(得分:0)

from collections import deque
from types import StringTypes

s = "A!\nB!\nC!\n<tag>\nD!\nE!\n</tag>\nF!\n<tag>\nG!\n</tag>"

def parse(parts):
    if type(parts) in StringTypes:
        parts = deque(parts.split("\n"))
    ret = []
    while parts:
        part = parts.popleft()
        if part[-1] == "!":
            ret.append(part[:-1])
        elif part == "<tag>":
            ret.append(parse(parts))
        elif part == "</tag>":
            return ret
    return ret

print parse(s)

我使用deque作为速度因为pop(0)会非常慢,并且反转列表并使用pop()会使函数更难阅读和理解。

我敢让任何人创建同样的正则表达式,同时也提高清晰度!

(顺便说一下,我想你也可以使用pyparsing模块来解决这个问题,因为它支持递归。)

编辑:更改了函数以期望字符串或双端队列作为参数,从而简化了调用。

答案 4 :(得分:0)

这是我解决问题的方法。它使用regexp和列表中的一些操作。

import re
my_str = "A!\nB!\n<tag>\nC!\n</tag>\nD!\nE!\n<tag>\nF!\nG!\n</tag>\nH!\n"

x = re.findall("^(?:.|\n)+?(?=\n<tag>)",str) + re.findall("(?<=</tag>\n)(?:.|\n)+?(?=\n<tag>\n)",str) + re.findall("(?<=>\n)(?:[^>]|\n)+(?=\n)$",my_str)


y =[]
for elem in x:
    y += elem.split('\n')
x = re.findall("((?<=<tag>\n)(?:.|\n)+?(?=\n</tag>\n))",my_str)
for elem in x:
    y.append(elem.split('\n'))   

print y 

它产生输出

['A!', 'B!', 'D!', 'E!', 'H!', ['C!'], ['F!', 'G!']]
但是,我没有太多时间来测试它。

我认为没有更简单的方法可以做到这一点,因为Python中有无递归正则表达式,请参阅SO thread

度过一个美好的夜晚(我的时区)。 ;)

注意:可能通过使用 xor (请参阅XOR in Regexp)将所有内容都包含在一个正则表达式中可能会更好一些,但我认为它会失去可读性

答案 5 :(得分:0)

如果我理解的所有条件都经过验证(例如:'<tag>'之前或'</tag>'之前的行上没有字符;对吗?),我认为以下代码完成了这项工作:

import re

RE = ('(\A\n*<tag>\n+)',
      '(\A\n*)',
      '(!\n*</tag>(?!\n*\Z)\n*)',
      '(!\n*</tag>\n*\Z)',
      '(!\n*<tag>\n+)',
      '(!\n*\Z)',
      '(!\n+)')

pat = re.compile('|'.join(RE))

def repl(mat, d = {1:"[['", 2:"['", 3:"'],'", 4:"']]", 5:"',['", 6:"']", 7:"','"}):
    return d[mat.lastindex]

ch =  .... # a string to parse
dh = eval(pat.sub(repl,ch))
施加

ch1 = '''

A!
B!
C!
<tag>
D!


E!
</tag>
F!
<tag>
G!
</tag>


'''

ch2 = '''A!
B!
C!



<tag>
D!
E!
</tag>
F!
<tag>
G!
</tag>

H!

'''

ch3 = '''


A!
B!
C!
<tag>
D!
E!
</tag>
Fududu!gutuyu!!
<tag>
G!

</tag>

H!'''

ch4 = '''<tag>
A!
B!

</tag>
C!
<tag>
D!
E!
</tag>
F!
<tag>
G!

</tag>

H!'''

import re

RE = ('(\A\n*<tag>\n+)',
      '(\A\n*)',
      '(!\n*</tag>(?!\n*\Z)\n*)',
      '(!\n*</tag>\n*\Z)',
      '(!\n*<tag>\n+)',
      '(!\n*\Z)',
      '(!\n+)')

pat = re.compile('|'.join(RE))

def repl(mat, d = {1:"[['", 2:"['", 3:"'],'", 4:"']]", 5:"',['", 6:"']", 7:"','"}):
    return d[mat.lastindex]


for ch in (ch1,ch2,ch3,ch4):
    print ch
    dh = eval(pat.sub(repl,ch))
    print dh,'\n',type(dh)
    print '\n\n============================='

结果

>>> 


A!
B!
C!
<tag>
D!


E!
</tag>
F!
<tag>
G!
</tag>



['A', 'B', 'C', ['D', 'E'], 'F', ['G']] 
<type 'list'>


=============================
A!
B!
C!



<tag>
D!
E!
</tag>
F!
<tag>
G!
</tag>

H!


['A', 'B', 'C', ['D', 'E'], 'F', ['G'], 'H'] 
<type 'list'>


=============================



A!
B!
C!
<tag>
D!
E!
</tag>
Fududu!gutuyu!!
<tag>
G!

</tag>

H!
['A', 'B', 'C', ['D', 'E'], 'Fududu!gutuyu!', ['G'], 'H'] 
<type 'list'>


=============================
<tag>
A!
B!

</tag>
C!
<tag>
D!
E!
</tag>
F!
<tag>
G!

</tag>

H!
[['A', 'B'], 'C', ['D', 'E'], 'F', ['G'], 'H'] 
<type 'list'>


=============================
>>>