正则表达式模式匹配交替的子模式

时间:2010-08-20 23:48:45

标签: php regex pcre

我正在尝试设计一个正则表达式模式(在PHP中),它允许任意两个子模式的交替。因此,如果模式A匹配一组三个字母,而B匹配一组2个数字,那么所有这些都可以:

aaa
aaa66bbb
66
67abc
12abc34def56ghi78jkl

我不介意哪个子模式开始或结束序列,只是在第一次匹配后,子模式必须交替。我完全被这个难过 - 任何建议都会感激不尽!

4 个答案:

答案 0 :(得分:2)

"/^(?:$A(?:$B$A)*$B?|$B(?:$A$B)*$A?)\$/"

将匹配模式A,然后匹配多个交替模式B和模式A,并且可能是最终的B ...或者B,然后是多个A-B对加上A,如果它在那里。

我已经把它变成了一个字符串(并且逃过最后的$),因为你要进行一些插值。如果你想让?匹配正确的东西,确保$ A和$ B在某种分组中(如括号)。在您的示例中,$ A可能是'([a-zA-Z] {3})',$ B可能是'(\ d \ d)'。

注意,如果你想匹配一些相同的字母或数字,或者相同的字母或数字的实例,你需要做的反向引用的一些魔法 - 可能是命名的,因为任何带编号的反向引用将取决于你想要的那个之前(或者你想要的那个和你所在的那个之间)的捕获组的数量,但是如果子模式有括号,那么这个数字会变得复杂在他们中间。

答案 1 :(得分:2)

以下是一般解决方案:

^(?:[a-z]{3}(?![a-z]{3})|[0-9]{2}(?![0-9]{2}))+$

这是一个简单的替换 - 三个字母或两个数字 - 但负向前瞻确保相同的替代品永远不会连续两次匹配。这是针对PHP的稍微优雅的解决方案:

/^(?:([a-z]{3})(?!(?1))|([0-9]{2})(?!(?2)))+$/

不是多次输入相同的子模式,而是可以让他们捕获组并使用(?1)(?2)等来再次将它们应用到您想要的任何地方 - 在这种情况下,在向前看符号。

答案 2 :(得分:0)

查看this(并查看conditional subpatterns)。我个人从未使用它们,但似乎是你正在寻找的。

答案 3 :(得分:0)

/\b(?:(([a-z])\2\2)(?:(([0-9])\4)\1)*(?:([0-9])\5)?|(([0-9])\7)(?:(([a-z])\9\9)\6)*(?:([a-z])\10\10)?)\b/

或者如果你想允许三个一组中的任何非数字字符:

/\b(?:((\D)\2\2)(?:((\d)\4)\1)*(?:(\d)\5)?|((\d)\7)(?:((\D)\9\9)\6)*(?:(\D)\10\10)?)\b/

这将匹配由两个交替组组成的任何模式,一组由相同char的3倍组成,另一组由相同数字的2倍组成。

此正则表达式将匹配

aaa
11
bbb22
33ccc
ddd44ddd
55eee55
fff66fff66
77ggg77ggg

但不是

aaa11bbb