不含特定子串的正则表达式:验证不含baa的表达式及长度2字符串合规性
关于正则表达式匹配不含特定子串的问题解答
1. 匹配不包含特定子串的正则表达式思路
要匹配不包含某个特定子串的字符串,最常用的方法是利用**负向预查(negative lookahead)**来实现。举个例子,如果我们要匹配所有不包含abc的字符串,对应的正则表达式可以写成:
^(?!.*abc).*$
简单解释下原理:
^匹配字符串开头(?!.*abc)是负向预查,断言从当前位置开始,整个字符串中不存在abc这个子串(.*表示任意数量的任意字符,用来覆盖abc可能出现的任意位置).*匹配任意数量的任意字符(如果需要匹配换行符,可以开启单行模式,或者用[\s\S]*代替.*)
这是通用方案,针对不同的子串,有时候可以写出更高效的正则,但负向预查是最通用、最容易理解的方法。
2. 字母集{a,b}中不含子串baa的正则表达式验证
直接给出结论:a* ((aa)* b*)这个正则表达式不能正确匹配所有不含baa的单词,我们一步步拆解分析:
正则表达式a* ((aa)* b*)的匹配范围
这个正则的结构是:任意数量的a,后面跟着「任意数量的aa + 任意数量的b」。换句话说,所有由这个正则生成的字符串,b只能出现在字符串的末尾部分,b后面不能有任何a——因为b*之后没有其他匹配规则了。
被遗漏的合法字符串
比如字符串ba,它显然不含baa,但ba无法被这个正则匹配(因为b后面跟着a,不符合正则的结构)。这说明这个正则的范围太窄,漏掉了很多符合要求的字符串。
长度为2的字符串验证
字母集{a,b}中长度为2的字符串有4个:aa、ab、ba、bb。这四个字符串都不含baa(长度只有2,根本不可能包含长度为3的子串baa),所以它们都属于合法范围。
但用a* ((aa)* b*)匹配的话:
aa、ab、bb都能被匹配;ba无法被匹配,而ba是符合「不含baa」条件的。
所以长度为2的字符串里,存在符合条件但不被该正则匹配的情况,进一步证明这个正则是不正确的。
如果要写出正确的正则,可以基于状态机推导,比如(a* b (a | ε))* a*(或等价形式),核心是保证每次出现b之后,最多只能跟一个a,避免出现baa的情况。
内容的提问来源于stack exchange,提问作者Raj Chauhan
相关产品推荐
相关产品推荐

