Python正则表达式是否与Ruby';什么是原子分组?
Ruby的正则表达式有一个称为原子分组Python正则表达式是否与Ruby';什么是原子分组?,python,ruby,regex,Python,Ruby,Regex,Ruby的正则表达式有一个称为原子分组(?>regexp)的特性,如前所述,Python的re模块中是否有任何等价物 (?p…) 与正则括号类似,但组匹配的子字符串可以通过符号组名在正则表达式的其余部分中访问。组名必须是有效的Python标识符,并且每个组名只能在正则表达式中定义一次。符号组也是一个编号的组,就像该组没有命名一样。因此,下面示例中名为id的组也可以作为编号的组1引用 例如,如果模式为(?p[a-zA-Z_uw*),则可以通过匹配对象的方法(如m.group('id')或m.end
(?>regexp)
的特性,如前所述,Python的re
模块中是否有任何等价物
(?p…)
与正则括号类似,但组匹配的子字符串可以通过符号组名在正则表达式的其余部分中访问。组名必须是有效的Python标识符,并且每个组名只能在正则表达式中定义一次。符号组也是一个编号的组,就像该组没有命名一样。因此,下面示例中名为id的组也可以作为编号的组1引用
例如,如果模式为(?p[a-zA-Z_uw*),则可以通过匹配对象的方法(如m.group('id')或m.end('id'))的参数中的名称来引用组,也可以通过正则表达式本身中的名称(使用(?p=id))和给.sub()的替换文本(使用\g)来引用组
(?p=名称)
Python不直接支持此功能,但您可以通过使用零宽度的前瞻断言(
(?=RE)
)来模拟它,该断言从当前点以您想要的相同语义进行匹配,将命名组((?PRE)
)放入前瞻中,然后使用命名的反向引用((?p=name)
)完全匹配零宽度断言匹配的内容。结合在一起,这将为您提供相同的语义,代价是创建一个额外的匹配组和大量语法
例如,您提供的链接给出了
/"(?>.*)"/.match('"Quote"') #=> nil
我们可以在Python中模拟这一点:
re.search(r'"(?=(?P<tmp>.*))(?P=tmp)"', '"Quote"') # => None
您也可以使用匿名组和数字反向引用,但这会充满线条噪音:
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)
随着我们扩展搜索字符串的长度,这一点变得更加引人注目。根据,答案是否定的。创建A是为了将其添加到Python 3中,但被拒绝,取而代之的是支持它的新模块:
>>> import regex
>>> regex.match('"(?>.*)"', '"Quote"')
>>> regex.match('"(.*)"', '"Quote"')
<_regex.Match object at 0x00C6F058>
导入正则表达式
>>>regex.match(“(?>.*”,““引号”)
>>>regex.match(“(.*”,““Quote”)
注意:regex
也适用于Python2。它似乎不适用
大多数现代正则表达式风格都支持原子分组,包括JGsoft风格、Java、PCRE、.NET、Perl和Ruby
您可以通过使用非捕获组来模拟它们的非捕获性,
(?:RE)
,但是如果我读对了,这仍然不会给您带来优化好处。命名匹配与原子分组不同。您链接的regex
模块与您链接的python bug中的regex模块相同,即python 3.3中不支持stdlib@J.F.Sebastian哦,好的!我认为Python3仍然使用re
模块,因为我只使用过Python2,我不确定,并假设它引用了相同的模块。(编辑:NVM that,刚刚看到了问题所在:我在看,它与我在回答中提到的一个重复关闭。我会更新它)现在,你已经更改了链接,我之前的评论没有意义。记录在案的是链接,Python的“re”库仍然如此,但值得注意的是,“regex”库确实提供了原子分组和所有格量化。有些情况下,“伪原子分组”提供了最小的加速,但与使用正则表达式(包括“普通”和所有格量词)相比相形见绌。我还发现使用“伪原子分组”似乎是合适的,但是它实际上运行得非常慢:^\w+:
在一个以冒号结尾的非常长的字符串上
[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
>>> import regex
>>> regex.match('"(?>.*)"', '"Quote"')
>>> regex.match('"(.*)"', '"Quote"')
<_regex.Match object at 0x00C6F058>