Python正则表达式 - 匹配新线与众多匹配

时间:2014-01-13 00:42:48

标签: python regex

我正在尝试创建一种字典解析器。在文本文件中,我有以下格式的文本:

<topic>some_title1:<start>
test_text<end>

<topic>title_2:<start>
test1
test2<end>

在每种情况下,<topic>表示密钥,<start><end>之间的文字是值。键总是一行,而值可能(并且很可能会)多于一行。

我的正则表达式如下:

p = re.compile("<topic>(.+):<start>\n(.+)<end>")

我正在使用p.findall(data)来获取键/值对。

如果没有re.DOTALL,我只会得到一个匹配,这是第一个匹配(some_title1,其值为test_text)。但是,我需要两场比赛。

所以,我尝试使用re.DOTALL

另一方面,这也给出了一个匹配,但不正确:

some_title1:<start>\ntest_text<end>\n\n<topic>title_2,其对应值为test1\ntest2

我该如何解决这个问题?我(希望)希望保持类似标签的结构。

2 个答案:

答案 0 :(得分:3)

你可以试试这个:

>>> import re
>>> t = '''<topic>some_title1:<start>
test_text<end>

<topic>title_2:<start>
test1
test2
<end>'''
>>> q = re.findall(r'<topic>([^:<]+?):<start>([^<]+?)<end>', t)
[('some_title1', '\ntest_text'), ('title_2', '\ntest1\ntest2\n')]
>>> dict(q)
{'some_title1': '\ntest_text', 'title_2': '\ntest1\ntest2\n'}

或者在一行中:

>>> dict(re.findall(r'<topic>([^:<]+?):<start>([^<]+?)<end>', t))
{'some_title1': '\ntest_text', 'title_2': '\ntest1\ntest2\n'}

这可以捕获多行值。当然,xml在这里工作会更好。但根据您的数据结构,关键似乎是通过匹配>以外的任何字符来收集<<之间的文字。换句话说,您的密钥应与此组匹配:([^:<]+?)。您的值应与此组匹配:([^<]+?)

答案 1 :(得分:2)

如果您可以用其他方式表示数据,这将更容易。假设您代表您的数据:

<topic title="some title1">test_text1</topic>
<topic title="some title2">test_text2</topic>

现在可以使用BeautifulSoup轻松访问标题和内容:

from bs4 import BeautifulSoup

xml = """
    <topic title="some title1">test_text1</topic>
    <topic title="some title2">test_text2</topic>
    """

soup = BeautifulSoup(xml)
for topic in soup.find_all('topic'):
    print topic['title'], topic.text

这将产生

some title1 test_text1
some title2 test_text2