【问题标题】:Regex - How to work with sub groups [duplicate]正则表达式 - 如何使用子组[重复]
【发布时间】:2012-09-20 22:18:28
【问题描述】:

可能重复:
Matching Nested Structures With Regular Expressions in Python

我正在尝试匹配 w​​iki 页面中的一组数据。下面列出了我正在使用的一些 python 代码。问题是它会在自己组的末尾返回到页面中的最后一个}}

def findPersonInfo(self):
    if (self.isPerson == True):
        regex = re.compile(r"{{persondata(.*)}}",re.IGNORECASE|re.UNICODE|re.DOTALL)
        result = regex.search(self._rawPage)
        if result:
            print 'Match found: ', result.group()

wiki 页面内容示例:

*[http://www.jsc.nasa.gov/Bios/htmlbios/acaba-jm.html NASA biography]

{{NASA Astronaut Group 19}}

{{Persondata
|NAME= Acaba, Joseph Michael "Joe"
|ALTERNATIVE NAMES=
|SHORT DESCRIPTION=[[Hydrogeologist]]
|DATE OF BIRTH={{Birth date and age|1967|5|17}}
|PLACE OF BIRTH=[[Inglewood, California]]
|DATE OF DEATH=
|PLACE OF DEATH=
}}
{{DEFAULTSORT:Acaba, Joseph M.}}
[[Category:1967 births]]

我当前的正则表达式返回以下字符串:

{{Persondata
|NAME= Acaba, Joseph Michael "Joe"
|ALTERNATIVE NAMES=
|SHORT DESCRIPTION=[[Hydrogeologist]]
|DATE OF BIRTH={{Birth date and age|1967|5|17}}
|PLACE OF BIRTH=[[Inglewood, California]]
|DATE OF DEATH=
|PLACE OF DEATH=
}}
{{DEFAULTSORT:Acaba, Joseph M.}}

我希望它返回:

{{Persondata
|NAME= Acaba, Joseph Michael "Joe"
|ALTERNATIVE NAMES=
|SHORT DESCRIPTION=[[Hydrogeologist]]
|DATE OF BIRTH={{Birth date and age|1967|5|17}}
|PLACE OF BIRTH=[[Inglewood, California]]
|DATE OF DEATH=
|PLACE OF DEATH=
}}

棘手的一点是它需要计算其他{{ 打开和}} 关闭才能知道我想停在哪个组,但我不知道如何让正则表达式做到这一点。

【问题讨论】:

  • 你应该使用正确的Wiki parser... 这不是常规语言 BTW
  • @JBernardo - 我不需要完整的解析器,我只需要整个页面中的一个部分,我可以将其拆分为键/值对。
  • @Justin808 这就是您需要解析器的原因。正则表达式不适用于具有任意深度级别的语言。您可以使其适用于某些特定情况,但您不应该
  • @JBernardo - 我想,但我宁愿不必使用完整的外部 wiki 解析器。我希望使用带有一些 .splits() 的正则表达式结果来获得我需要的东西。我正在尝试使用系统上预装的东西。
  • 带有嵌套的 {{ 你真的应该使用解析器/语法 ....

标签: python regex


【解决方案1】:

{{persondata(.*)}} 会贪婪匹配。 IE。它将尝试返回最长的匹配项。如果你想获得最短的匹配,你应该使用{{persondata(.*?)}}。 (是不是没有这个名字,也许节俭搭配?)

但是,在这种情况下,您的字符串中还有另一个 }}。你可以做一些聪明的事情,比如{{persondata((?:.*)}}(?:.*))}},但一般来说,一旦你到达递归结构(嵌套自己的结构),你应该放弃正则表达式并转向正确的解析解决方案。

你可能想看看pyparsing

【讨论】:

  • r"{{persondata([^}]*)}}" 假设没有嵌套的花括号 ...
  • 但这会产生同样错误的结果,在|DATE OF BIRTH={{Birth date and age|1967|5|17}} 之后终止。
  • 所以在标准python中做到这一点的唯一方法是不使用正则表达式并编写我的一个函数来处理递归大括号?看起来很奇怪,我用过的所有其他语言似乎都支持没有外部库的递归。
  • “支持递归”和“使用正则表达式解析递归结构”是有区别的。正如他们在编译器类中所说的正则表达式不能计数(即它们不维护堆栈来计算无限可嵌套的结构)。当然可以只使用纯 python 编写一个很好的递归下降解析器。
  • 嵌套的东西很糟糕......根据定义,正则表达式没有状态,因此不能匹配任意嵌套......但你可以匹配这个......但它会破坏其他任何东西......
【解决方案2】:

PyPI 上有一个为此目的而创建的模块。见mwparserfromhell

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多