正则表达式匹配ABCD随机字串
December 5th, 2008
Categories: 问答
前一段时间在chinaunix论坛上发现这样一则问题:
要求abcd四个字母连续,但每个字母有且仅出现一次,并且顺序可以不固定,也就是要匹配abcd adbc bcda等等情况
我说一下自己的解决思路。
- 第一个字母是abcd中的任意一个,因此正则式[abcd]即符合要求。第一个字母最简单。
- 第二个字母是abcd中的任意一个,但是不能使用第一步中已经使用过的字母。因此回退一步,将第一个字母括起来,以备引用([abcd])。不能使用\1,亦即(?!\1),它表示当前位置不出现\1,即第一个字母。至此,正则式如下:([abcd])(?!\1)([abcd])。
- 第三个字母与第二个字母的原理相同,但是它既不能使用第一个字母,也不能使用第二个字母。正则式如下:([abcd])(?!\1)([abcd])(?!\1|\2)([abcd])。
- 第四步无需多言,完整正则式如下:([abcd])(?!\1)([abcd])(?!\1|\2)([abcd])(?!\1|\2|\3)([abcd])。
回顾刚才的正则式,对于新手来说,或许(?!\1)是个不容易理解的地方。我就对此作用简单介绍。(?!...)的形式称为look around,与^或$一样,它只匹配位置,而不实际消耗字符。如果想匹配“某字串之后不出现某字串”这种情况,那么(?!)negative lookahead是不可缺少的。例如,如果想匹配q之后不出现u的字串,就可以使用q(?!u),它表示q后边不出现u。它可以匹配"Iraq","icq","qq"等字串。
如果您读到这里还没有头痛,请思考它与q[^u]的区别。
我的:
(?=.{0,3}a)(?=.{0,3}b)(?=.{0,3}c)(?=.{0,3}d).{4}
inspired by http://is.gd/cD8x
[Reply]
如果不是a-d,而是a-z最好用两个正则:
var reg1 = /[a-d]{4}/g;
var reg2 = /^(?!([a-d])\1)[a-d]{4}$/;
function findout(s, callback) {
var arr = s.match(reg1);
for(var i=0,len=arr.length;i<len;i++){
if(reg2.test(arr[i]))
callback(arr[i]);
}
}
findout('aabc abcd acbd adbc aecfegba cadb aebcd', function(s){
alert(s);
});
[Reply]
DemoJameson Reply:
February 8th, 2010 at 11:38 pm
第二个正则不符合要求,它只能确保前两个字母,以下字母也会被匹配:
abad、abcb……
[Reply]
不错不错,测试通过。比我的正则式要写得简洁、美观。
[Reply]