Python正则表达式是否与Ruby的原子分组等效?

时间:2012-11-27 04:23:50

标签: python ruby regex

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

4 个答案:

答案 0 :(得分:45)

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

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

的Ruby示例
/"(?>.*)"/.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文档中学到了这个技巧,该文档在(?>...)的文档中提到了它。)

除了具有正确的语义之外,它还具有适当的性能属性。如果我们从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

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

答案 1 :(得分:13)

根据this table,答案是否定的。创建RFE是为了将其添加到Python 3中,但被拒绝支持新的regex模块,该模块支持它:

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

注意:{2}也可以使用regex

答案 2 :(得分:0)

似乎没有。

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

  

大多数现代正则表达式支持原子分组,包括JGsoft风格,Java,PCRE,.NET,Perl和Ruby。

您可以使用非捕获组(?:RE)来模拟它们的非捕获性,但如果我正确读取它,那么仍然无法为您提供优化效果。

答案 3 :(得分:-2)

来自http://docs.python.org/2/library/re.html#regular-expression-syntax

(?P&LT;名称&gt; ...)

与常规括号类似,但是通过符号组名称名称可以在正则表达式的其余部分中访问该组匹配的子字符串。组名必须是有效的Python标识符,并且每个组名只能在正则表达式中定义一次。符号组也是编号组,就像组未命名一样。因此,下面示例中名为id的组也可以作为编号组1引用。

例如,如果模式是(?P [a-zA-Z _] \ w *),则可以通过匹配对象方法的参数在名称中引用该组,例如m.group('id') )或m.end('id'),以及正则表达式本身的名称(使用(?P = id))和.sub()的替换文本(使用\ g)。

(ΔP=名)

Matches whatever text was matched by the earlier group named name.