zhengrenzhe's blog   About

JS正则表达式中全局标志g对匹配的影响

最近在面试中遇到了一个关于正则表达式的问题,这里总结一下

有如下字符串和如下正则表达式:

var str = '+a+b+c+d';
var reg = /\+[a-z]\+/gi;

用字符串的match方法来根据正则匹配字符串,你认为匹配的是下面的结果么?

["+a+", "+b+", "+c+", "+d+"]

其实事实上是这个结果:

["+a+", "+c+"]

为什么会是下面这个结果呢?我不是已经加了g么,应该执行全局匹配啊,+a+完了不就是+b+么?问题就在于这个全局标志g。

当在正则中使用了全局标志g,代表在执行完一次匹配后继续执行匹配,直到字符串结束,但在使用g的时候,js引擎会记录上一次匹配的位置,在下一次匹配时,从上一次的位置的+1处开始匹配,也就是说当第一次找到+a+时,再次匹配的对象就是b+c+d这样当然找不到+b+,同理也找不到+d+了。

假如有一个函数,要你确定字母是否都被+所包围,那用上面的正则自然是没法满足需要了,但如果用循环之类的又太麻烦了,就想用正则解决该怎么办呢?下面是我的解决办法:

function check(str){
  // 找到类似+a这种结构的字符串,合并返回数组元素,移除非字母字符
  var res  = str.match(/\+[a-z]/gi).join().replace(/[^a-z]/gi,'');
  // 找到类似a+这种结构的字符串,合并返回数组元素,移除非字母字符
  var res2 = str.match(/[a-z]\+/gi).join().replace(/[^a-z]/gi,'');
  // 当两次找到的字符串想同时,则认为原始字符串的字母都被+所包围,因为+a+必然包含+a和a+,这样就避免了g记录位置所引发的问题
  if(res === res2){
    return true;
  }else{
    return false;
  }
}

← 知乎 Hackers三道题  contenteditable属性总结 →