使用正则表达式 (PCRE) 匹配 a^n b^n c^n(例如“aaabbbccc”)

2022-08-30 11:33:13

众所周知,现代正则表达式实现(最明显的是 PCRE)与正则语法的原始概念几乎没有共同之处。例如,您可以使用此正则表达式(演示)解析上下文无关语法 {anbn; n>0} (例如 )的经典示例:aaabbb

~^(a(?1)?b)$~

我的问题是:你能走多远?是否也可以使用PCRE解析上下文相关语法{anbn cn;n>0}(例如)?aaabbbccc


答案 1

受到NullUserExceptions答案的启发(他已经删除了,因为它在一个案例中失败了),我想我自己已经找到了一个解决方案:

$regex = '~^
    (?=(a(?-1)?b)c)
     a+(b(?-1)?c)
$~x';

var_dump(preg_match($regex, 'aabbcc'));    // 1
var_dump(preg_match($regex, 'aaabbbccc')); // 1
var_dump(preg_match($regex, 'aaabbbcc'));  // 0
var_dump(preg_match($regex, 'aaaccc'));    // 0
var_dump(preg_match($regex, 'aabcc'));     // 0
var_dump(preg_match($regex, 'abbcc'));     // 0

亲自尝试一下:http://codepad.viper-7.com/1erq9v


解释

如果您考虑没有正前瞻断言(该部分)的正则表达式,则有以下情况:(?=...)

~^a+(b(?-1)?c)$~

这只不过是检查是否存在任意数量的 s,后跟相等数量的 s 和 s。abc

这还不能满足我们的语法,因为s的数量也必须相同。我们可以通过检查 s 的个数等于 s 的个数来确保这一点。这就是前瞻断言中的表达式的作用:.这是必要的,所以我们不只匹配s的一部分。aab(a(?-1)?b)ccb


结论

我认为这令人印象深刻地表明,现代正则表达式不仅能够解析非正则语法,甚至可以解析非上下文无关的语法。希望这将平息“你不能用正则表达式做X,因为X不是常规的”的无休止的鹦鹉学舌。


答案 2

下面是使用 .NET 正则表达式平衡组的替代解决方案:

^(?'a'a)+(?'b-a'b)+(?(a)(?!))(?'c-b'c)+(?(b)(?!))$

不是PCRE,但可能很有趣。

示例位于:http://ideone.com/szhuE

编辑:为组a添加了缺少的平衡检查,以及一个在线示例。


推荐