Python 正则表达式:匹配最新版本中的括号(2019 年 2 月)

Python regexes: matching parentheses in newest version (Feb 2019)

1。关于 Python 正则表达式 2019.02.21

Python 正在升级 regex 模块。最新版本是从 2019 年 2 月 21 日开始的。您可以在这里查阅: https://pypi.org/project/regex/

会及时替换re模块。现在,您需要使用 pip install regex 手动安装它并导入 regex 模块而不是 re.


2。新的正则表达式功能

最新版本最酷的功能是递归模式。在这里阅读更多相关信息:https://bitbucket.org/mrabarnett/mrab-regex/issues/27

此功能可以找到匹配的括号 ( .. ) 或大括号 { .. }。以下网页说明了如何执行此操作:https://www.regular-expressions.info/recurse.html#balanced 我引用:

The main purpose of recursion is to match balanced constructs or nested constructs. The generic regex is b(?:m|(?R))*e where b is what begins the construct, m is what can occur in the middle of the construct, and e is what can occur at the end of the construct. For correct results, no two of b, m, and e should be able to match the same text. You can use an atomic group instead of the non-capturing group for improved performance: b(?>m|(?R))*e.  
 
A common real-world use is to match a balanced set of parentheses. \((?>[^()]|(?R))*\) matches a single pair of parentheses with any text in between, including an unlimited number of parentheses, as long as they are all properly paired.


3。我的问题

我正在尝试匹配花括号 { .. }。所以我简单地应用了上面网页中的正则表达式,但是我用 { 替换了 (。这给了我以下正则表达式:

{(?>[^{}]|(?R))*}

我在 https://regex101.com 上试了一下,效果很好(*):

我想更进一步,找到一组特定的匹配花括号,如下所示:

MEMORY\s*{(?>[^{}]|(?R))*}

结果很好:

但是当我尝试

SECTIONS\s*{(?>[^{}]|(?R))*}

未找到任何内容。没有比赛。 MEMORY{..}SECTIONS{..} 部分之间的唯一区别是后者有一些嵌套的花括号。所以问题应该在那里找到。但我不知道如何解决这个问题。


*注1:
https://regex101.com 上,您可以 select 正则表达式的 flavor。通常我 select Python,但这次我 selected PCRE(PHP) 因为 regex101 网站还没有应用最新的 Python 正则表达式升级。
为了确认结果,我还在我的终端中的一个简单的 python-session 中尝试了它,使用如下命令:
import regex
p = regex.compile(r"...")
text = """ ... """
p.findall(text)

* 注2:
我用于测试的文本是:

MEMORY
{
    /* Foobar */
    consectetur adipiscing elit,
    sed do eiusmod tempor incididunt
}
Lorem ipsum dolor sit amet,

SECTIONS
{
    ut labore et dolore magna aliqua.
    /* Foobar */
        FOO
        {
            /* Foobar */
            Ut enim ad minim veniam,
            quis nostrud exercitation ullamco
        }

        BAR
        {
            /* Foobar */
            laboris nisi
            ut
        }
    aliquip ex ea commodo consequat.
}
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

您使用 (?R) 构造递归整个模式,而您只想递归 {...} 子模式。用捕获组包裹它并用 subroutine:

递归
p = regex.compile(r"SECTIONS\s*({(?>[^{}]|(?1))*})")
for m in p.finditer(text):
    print(m.group())

参见Python regex demo online

请注意,您的第一个模式也存在同样的问题,如果您在那里添加嵌套的花括号,它将无法正常工作。修复为 MEMORY\s*({(?>[^{}]|(?1))*}).