Python正则表达式是否与Ruby的原子分组具有等价性?

2024-04-19 09:33:56 发布

您现在位置:Python中文网/ 问答频道 /正文

Ruby的正则表达式有一个称为原子分组(?>regexp)的特性,如here所述,Python的re模块中是否有任何等价物


Tags: 模块rehere特性rubyregexp原子
3条回答

根据this table,答案是否定的。创建RFE是为了将它添加到Python 3中,但被拒绝,取而代之的是支持它的新^{}模块:

>>> import regex
>>> regex.match('"(?>.*)"', '"Quote"')
>>> regex.match('"(.*)"', '"Quote"')
<_regex.Match object at 0x00C6F058>

注意:regex也可用于Python2

Python不直接支持此功能,但您可以通过使用零宽度的前瞻断言((?=RE))来模拟它,该断言从当前点以您想要的相同语义进行匹配,将命名组((?P<name>RE))放在前瞻内,然后使用命名的反向引用((?P=name))完全匹配零宽度断言匹配的内容。结合在一起,这将为您提供相同的语义,代价是创建一个额外的匹配组和大量语法

例如,您提供的链接给出了

/"(?>.*)"/.match('"Quote"') #=> nil

我们可以在Python中模拟这一点:

re.search(r'"(?=(?P<tmp>.*))(?P=tmp)"', '"Quote"') # => None

我们可以证明我正在做一些有用的事情,而不仅仅是发出线噪声,因为如果我们改变它,使内部组不吃最后的",它仍然匹配:

re.search(r'"(?=(?P<tmp>[A-Za-z]*))(?P=tmp)"', '"Quote"').groupdict()
# => {'tmp': 'Quote'}

您也可以使用匿名组和数字反向引用,但这会充满线条噪音:

re.search(r'"(?=(.*))\1"', '"Quote"') # => None

(完全公开:我从perl的^{}文档中学到了这个技巧,它在(?>...)文档中提到了它。)

除了具有正确的语义外,它还具有适当的性能属性。如果我们从perlre中移植一个示例:

[nelhage@anarchique:~/tmp]$ cat re.py
import re
import timeit


re_1 = re.compile(r'''\(
                           (
                             [^()]+           # x+
                           |
                             \( [^()]* \)
                           )+
                       \)
                   ''', re.X)
re_2 = re.compile(r'''\(
                           (
                             (?=(?P<tmp>[^()]+ ))(?P=tmp) # Emulate (?> x+)
                           |
                             \( [^()]* \)
                           )+
                       \)''', re.X)

print timeit.timeit("re_1.search('((()' + 'a' * 25)",
                    setup  = "from __main__ import re_1",
                    number = 10)

print timeit.timeit("re_2.search('((()' + 'a' * 25)",
                    setup  = "from __main__ import re_2",
                    number = 10)

我们看到了巨大的进步:

[nelhage@anarchique:~/tmp]$ python re.py
96.0800571442
7.41481781006e-05

当我们扩展搜索字符串的长度时,这只会变得更加引人注目

似乎不是

http://www.regular-expressions.info/atomic.html

Atomic grouping is supported by most modern regular expression flavors, including the JGsoft flavor, Java, PCRE, .NET, Perl and Ruby.

您可以通过使用非捕获组来模拟它们的非捕获性,(?:RE),但是如果我读对了,这仍然不会给您带来优化的好处

相关问题 更多 >