我认为这就是你想要的。
对于交替字符:
(?=(.)(?!\1)(.))(?:\1\2){2,}
\0 将是整个交替序列,\1 和 \2 是两个(不同的)交替字符。
对于连续 N 和 M 个字符,可能由其他字符分隔(在此处将 N 和 M 替换为数字):
(?=(.))\1{N}.*?(?=(?!\1)(.))\2{M}
\0 将是整个匹配,包括中缀。 \1 是重复(至少)N 次的字符,\2 是重复(至少)M 次的字符。
这是一个 Java 测试工具。
import java.util.regex.*;
public class Regex3 {
static String runNrunM(int N, int M) {
return "(?=(.))\\1{N}.*?(?=(?!\\1)(.))\\2{M}"
.replace("N", String.valueOf(N))
.replace("M", String.valueOf(M));
}
static void dumpMatches(String text, String pattern) {
Matcher m = Pattern.compile(pattern).matcher(text);
System.out.println(text + " <- " + pattern);
while (m.find()) {
System.out.println(" match");
for (int g = 0; g <= m.groupCount(); g++) {
System.out.format(" %d: [%s]%n", g, m.group(g));
}
}
}
public static void main(String[] args) {
String[] tests = {
"foobababababaf foobaafoobaaaooo",
"xxyyyy axxayyyya zzzzzzzzzzzzzz"
};
for (String test : tests) {
dumpMatches(test, "(?=(.)(?!\\1)(.))(?:\\1\\2){2,}");
}
for (String test : tests) {
dumpMatches(test, runNrunM(3, 3));
}
for (String test : tests) {
dumpMatches(test, runNrunM(2, 4));
}
}
}
这会产生以下输出:
foobababababaf foobaafoobaaaooo <- (?=(.)(?!\1)(.))(?:\1\2){2,}
match
0: [bababababa]
1: [b]
2: [a]
xxyyyy axxayyyya zzzzzzzzzzzzzz <- (?=(.)(?!\1)(.))(?:\1\2){2,}
foobababababaf foobaafoobaaaooo <- (?=(.))\1{3}.*?(?=(?!\1)(.))\2{3}
match
0: [aaaooo]
1: [a]
2: [o]
xxyyyy axxayyyya zzzzzzzzzzzzzz <- (?=(.))\1{3}.*?(?=(?!\1)(.))\2{3}
match
0: [yyyy axxayyyya zzz]
1: [y]
2: [z]
foobababababaf foobaafoobaaaooo <- (?=(.))\1{2}.*?(?=(?!\1)(.))\2{4}
xxyyyy axxayyyya zzzzzzzzzzzzzz <- (?=(.))\1{2}.*?(?=(?!\1)(.))\2{4}
match
0: [xxyyyy]
1: [x]
2: [y]
match
0: [xxayyyy]
1: [x]
2: [y]
说明
-
(?=(.)(?!\1)(.))(?:\1\2){2,} 有两个部分
-
(?=(.)(?!\1)(.)) 使用前瞻建立 \1 和 \2
- 嵌套的负前瞻确保
\1 != \2
- 使用前瞻捕获让
\0 拥有整个匹配项(而不仅仅是“尾”端)
-
(?:\1\2){2,} 捕获 \1\2 序列,该序列必须至少重复两次。
-
(?=(.))\1{N}.*?(?=(?!\1)(.))\2{M} 包含三个部分
-
(?=(.))\1{N} 在前瞻中捕获 \1,然后匹配它 N 次
-
.*? 允许使用中缀来分隔两个运行,但不愿意让它尽可能短
-
(?=(?!\1)(.))\2{M}
运行正则表达式将匹配更长的运行,例如run(2,2) 匹配 "xxxyyy":
xxxyyy <- (?=(.))\1{2}.*?(?=(?!\1)(.))\2{2}
match
0: [xxxyy]
1: [x]
2: [y]
此外,它不允许重叠匹配。即"xx11yyy222"中只有一个run(2,3)。
xx11yyy222 <- (?=(.))\1{2}.*?(?=(?!\1)(.))\2{3}
match
0: [xx11yyy]
1: [x]
2: [y]