为什么要写这么一篇文章呢?是因为自己最近在研究和学习正则表达式,然后在RegexGolf上练习技能的时候遇到了这么一道题目,觉得很有趣。我当时虽然也解决了这个问题,但是正则表达式写的有点长,而且也只算是一种取巧的解决方案。因为如果测试用例再多一点可能我写的这个正则表达式就不能够满足需求了。
后来在复盘这道题目的解决方案的时候,查阅了很多相关的资料。发现了更简洁,更准确的答案。当我看到答案的那一瞬间,我忽然发现自己当初距离这个答案其实也不远,如果自己当时再好好研究一下,有可能就想出了更简洁的答案了。当然,也许最终还是没有想出来,那里有那么多的如果呢😂。
说了这么多,让我们来看一下这道题目吧。如下图所示:
我们需要匹配左边的这些字符串,同时排除右边的这些字符串。不知道大家之前有没有做过类似的题目,现在大家就可以测试一下自己的正则的水平。个人感觉如果这道题目可以做出来的话,那么你的正则水平至少是中等偏上的水平啦。没有做出来也没有关系,毕竟在平时的开发过程中我们很难会遇到这种需求,不过也可以学习一下。加深一下自己对正则匹配过程的理解。
我当时看了题目的提示,知道是匹配素数,但是对于如何匹配一个素数我却是不知道的。于是我就取了个巧,在测试用例不是很多的情况下,可以进行穷举呀。于是我就写下了下面的答案:
^(?!(?:(x{2}){2,}|(x{3}){2,}|(x{5}){2,})$)
虽然有点长,但是好歹也算是通过了测试用例。
对正则表达式学习的比较深入的一些同学,看到了上面的正则应该很快就知道是什么意思了。我可以先简单的给大家讲解一下。上面的正则表达式匹配的过程是这样的:
^
:匹配一行的开始。(?!...)
:否定的顺序环视,匹配一个位置,后面紧跟着的是需要排除的条件。(?:)
:非捕获型括号,在这里用来限制多选结构的作用范围,当然在这里也可以使用捕获型的括号。(x{2}){2,}
:首先{2,}
限定了前面的表达式(x{2})
出现的次数只能是两次或者两次以上。(x{2})
表示需要匹配两个x
。(x{3}){2,}
和(x{5}){2,}
:这两个部分跟上面的正则片段是类似的意思。$
:匹配一行的结尾。
所以上面的正则表达式表示的意思就是匹配一个字符串的开始,然后紧接着字符串中x的个数不能是2个x的2倍或者以上,不能是3个x的2倍或者以上,不能是