如果你匹配了正则表达式
(?=(.{3}))(?=.+\1)
到字符串
ZABABABCACACABAABADEFGDEF
将有 7 个匹配项(空字符串),其中每个匹配项的捕获组 1 的内容是如下所示的 3 个字母字符串。
ZABABABCACACABAABADEFGDEF
0123456789012345678901234
ABA
BAB
ABA
CAC
ACA
ABA
DEF
Demo
每个这三个字符的字符串后跟相同的三个字符,这些字符在字符串的其余部分中至少出现一次。结果,重复了一些匹配。因此我们必须提取数组的唯一值
["ABA", "BAB", "ABA", "CAC", "ACA", "ABA", "DEF"]
获得
["ABA", "BAB", "CAC", "ACA", "DEF"]
作为在字符串中至少出现两次的 3 个字符的字符串。
(?=(.{3})) 的第一个匹配发生在正则表达式引擎的内部指针紧邻 Z 之前,并且捕获组 1 包含 ZAB。我们现在在字符串后面查找捕获组 1 的内容的匹配项,从 Z 右侧开始之后。因此,我们需要.+,而不是(?=.+\1) 中的.*。没有(?=.+\1)的匹配,所以匹配失败。由于环视不消耗任何字符,因此正则表达式引擎的内部指针没有移动。
然后内部指针向前移动一个字符,到紧挨第一个A 之前的位置,捕获组1 的内容变为ABA。从第二个 A 开始,在偏移量 3 处找到匹配,之后内部指针再次向前移动一个字符,到紧挨第一个 B 之前的位置,并重复该过程。
假设正则表达式
(?=(.{3})).+\1
改为使用。在得出ZAB 在字符串中仅出现一次的结论后,指针位于第一个A 之前,并且捕获组1 包含ABA。 .+\1 然后匹配 ABABABCACACABAABA(表明 ABA 重复)。但是,内部指针随后被移动到第一个 D 之前的位置,导致我们错过了几个重复的 3 字符字符串。使.+ 不贪婪((?=(.{3})).+?\1 会有所帮助,但我们仍然会错过BAB 和ACA。