Ruby的正则表达式有一种称为原子组合的功能(?>regexp)
,在这里描述,Python的re
模块中是否有相应的功能?
(?=RE)
)来模拟它,该前瞻从当前点开始匹配具有您所需的相同语义,将命名组((?P<name>RE)
)放在前瞻内部,然后使用命名反向引用((?P=name)
)精确匹配零宽度断言匹配的内容。将它们结合起来,就可以以相同的语义实现,但需要创建一个额外的匹配组和大量的语法。/"(?>.*)"/.match('"Quote"') #=> nil
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
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
^\w+:
。 - grjashregex
模块与你提供的 Python bug 中的 regex
模块是同一个模块,也就是说,在 Python 3.3 的标准库中没有支持该模块。 - jfsre
模块,因为我只用过Python 2,所以不确定,并且假设它指的是同一个模块。 (编辑: 不用管那个了,刚看到错了:我看的是这个RFE,它被关闭为我在答案中提到的那个的重复项。我会更新它) - mgibsonbr看起来不是这样。
http://www.regular-expressions.info/atomic.html
原子分组被大多数现代正则表达式引擎所支持,包括JGsoft风格、Java、PCRE、.NET、Perl和Ruby。来自http://docs.python.org/2/library/re.html#regular-expression-syntax
(?P<name>...)
类似于普通括号,但是通过符号组名name可以在正则表达式的其余部分中访问与组匹配的子字符串。组名必须是有效的Python标识符,并且每个组名必须在正则表达式中仅定义一次。符号组也是一个编号组,就像该组没有命名一样。因此,下面示例中命名为id的组也可以作为编号组1进行引用。
例如,如果模式是(?P[a-zA-Z_]\w*),则组可以通过其名称在match对象的方法参数中引用,例如m.group('id')或m.end('id'),并且还可以通过名称在正则表达式本身(使用(?P=id))和提供给.sub()的替换文本(使用\g)中进行引用。
(?P=name)
Matches whatever text was matched by the earlier group named name.