你好!以下是关于"可选的非捕获组"是否多余的问题:
下面这个正则表达式:
(?:wo)?men
语义上等同于以下正则表达式?
(wo)?men
你好!以下是关于"可选的非捕获组"是否多余的问题:
下面这个正则表达式:
(?:wo)?men
语义上等同于以下正则表达式?
(wo)?men
(?:wo)?men
和(wo)?men
在语义上是等价的,但从技术上来说是不同的,即前者使用的是非捕获组,而后者使用的是捕获组。因此,问题是为什么我们有了捕获组还要使用非捕获组呢?另外,它只是使我们的匹配更加清晰:
您可以使用非捕获组来保留组织或分组的好处,但不会增加捕获的开销。
将现有的正则表达式重构为非捕获组以转换捕获并不是一个好主意,因为这可能会破坏代码或需要过多的努力。
在另一个问题中,有人提出了相同的问题,我用Python提供了一个带有示例的答案:
它并没有"具有相同的效果"——在一个情况下,组被捕获并可访问,在另一个情况下,它仅用于完成匹配。
当人们不感兴趣访问组的值时,他们使用非捕获组——为了在出现多个匹配项的情况下节省空间,但也为了在正则表达式引擎针对此进行优化的情况下获得更好的性能。
以下是一个无用的Python示例来说明这一点:
from timeit import timeit
import re
chars = 'abcdefghij'
s = ''.join(chars[i % len(chars)] for i in range(100000))
def capturing():
re.findall('(a(b(c(d(e(f(g(h(i(j))))))))))', s)
def noncapturing():
re.findall('(?:a(?:b(?:c(?:d(?:e(?:f(?:g(?:h(?:i(j))))))))))', s)
print(timeit(capturing, number=1000))
print(timeit(noncapturing, number=1000))
输出:
5.8383678999998665
1.0528525999998237
# noinspection RegExpUnnecessaryNonCapturingGroup
re.findall('(?:a(?:b(?:c(?:d(?:e(?:f(?:g(?:h(?:i(j))))))))))', s)
c = re.findall('(a(b(c(d(e(f(g(h(i(j))))))))))', s)
nc = re.findall('(?:a(?:b(?:c(?:d(?:e(?:f(?:g(?:h(?:i(j))))))))))', s)
c
是一个由 10 元组组成的列表 ([('abcdefghij', 'bcdefghij', ..), ..]
),而 nc
则是由单个字符串组成的列表 (['j', ..]
)。