正则表达式匹配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]的区别。

Tags:

4 Responses to “正则表达式匹配ABCD随机字串”

  1. 那个谁
    December 20th, 2008 at 03:42
    1

    我的:
    (?=.{0,3}a)(?=.{0,3}b)(?=.{0,3}c)(?=.{0,3}d).{4}

    inspired by http://is.gd/cD8x

    [Reply]

  2. November 14th, 2009 at 17:31
    2

    如果不是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:

    第二个正则不符合要求,它只能确保前两个字母,以下字母也会被匹配:
    abad、abcb……

    [Reply]

  3. December 20th, 2008 at 03:50
    3

    不错不错,测试通过。比我的正则式要写得简洁、美观。

    [Reply]

Leave a Comment