1

我想从维基百科中提取信息框块。下面是一个示例输入文件:

{{some text}}
some other text
{{Infobox President
birth|d/m/y
other_inner_text:{{may contain curly bracket}}
other text}}
some other text
or even another infobox
{{Infobox Cabinet
same structure
{{text}}also can contain {{}}
}}
can be some other text...

我希望解析结果返回两个 Infobox 块:

{{Infobox President
birth|d/m/y
other_inner_text:{{may contain curly bracket}}
other text
}}

{{Infobox Cabinet
same structure
{{text}}also can contain {{}}
}}

任何人都知道如何在 python 中使用正则表达式来实现这一点?

4

3 回答 3

2

为了匹配嵌套结构,一些正则表达式方言提供递归模式,如(?R). 这个(?R)东西基本上是说“这个表达式匹配的东西”。

标准 pythonre不支持这一点,但最终将替换的较新的正则表达式re模块支持。这是一个完整的例子。

text = """
{{some text}}
some other text
{{Infobox President
birth|d/m/y
other_inner_text:{{may contain {curly} bracket}}
other text}}
some other text
or even another infobox
{{Infobox Cabinet
same structure
{{text}}also can contain {{}}
}}
can be some other text...
"""

import regex

rx = r"""
{{                    # open
(                     # this match
    (?:               # contains...
        [^{}]         # no brackets
        |             # or
        }[^}]         # single close bracket
        |             # or
        {[^{]         # single open bracket
        |             # or
        (?R)          # the whole expression once again <-- recursion!
    )*                # zero or more times
)                     # end of match
}}                    # close
"""

rx = regex.compile(rx, regex.X | regex.S)

for p in rx.findall(text):
    print 'FOUND: (((', p, ')))'

结果:

FOUND: ((( some text )))
FOUND: ((( Infobox President
birth|d/m/y
other_inner_text:{{may contain {curly} bracket}}
other text )))
FOUND: ((( Infobox Cabinet
same structure
{{text}}also can contain {{}}
)))

有关递归正则表达式的详细说明,请参阅此博客条目

在此处输入图像描述

(忍不住偷了这个)。


也就是说,使用基于解析器的解决方案可能会更好。例如,请参阅使用 pyparsing 解析嵌套表达式

于 2012-05-20T23:18:55.600 回答
1

它不是 python,但这个答案可能会对你有所帮助。它甚至包括一个(不是快速但肮脏的)正则表达式,可以处理一级嵌套模板。

一般的答案是否定的,正则表达式无法解析嵌套结构。有关如何从 mediawiki api 获取分析树的链接,请参阅链接的答案。

于 2012-05-20T21:58:48.793 回答
1

正则表达式

{{Infobox(?:(?!}}|{{).)*(?:{{(?:(?!}}|{{).)*}}(?:(?!}}|{{).)*)*.*?}}

还有我对 Perl 的尝试,但我并不流利

while ($subject =~ m/\{\{Infobox(?:(?!\}\}|\{\{).)*(?:\{\{(?:(?!\}\}|\{\{).)*\}\}(?:(?!\}\}|\{\{).)*)*.*?\}\}/sg) {
    # matched text = $&
}

只要它们是平衡的,它将适用于无限对的“{{ some text }}”。它不支持该对的嵌套文本,但不是必需的。

请注意,如果仅在 1 次解决方案中未使用替代解决方案,则最好寻找替代解决方案。维护这样的正则表达式是残酷的。

于 2012-05-20T22:19:13.327 回答