所以我有一个这样的字符串:
A!
B!
C!
<tag>
D!
E!
</tag>
F!
<tag>
G!
</tag>
是否可以用正则表达式解析它,所以我得到这个输出(列表):
[A, B, C, [D, E], F, [G]]
基本上我正在寻找一种方法来分割字符串!和标记 ...并且标记部分可以在任何地方发生......并且多个时间(但不递归...意味着标签内的标签......这不会发生)。整个事情似乎是正常的...这是否可以与正则表达式一起使用?
编辑:我正在使用Python
EDIT2:我只使用A,B,C ......作为表示......这些可以是由字母和数字组成的任何字符串
答案 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'>
=============================
>>>