1、exec

如果 exec() 找到了匹配的文本,则返回一个结果数组。否则,返回 null。

此数组的第 0 个元素是与正则表达式相匹配的文本
第 1 个元素是与 RegExpObject 的第 1 个子表达式相匹配的文本(如果有的话),
第 2 个元素是与 RegExpObject 的第 2 个子表达式相匹配的文本(如果有的话),以此类推。
除了数组元素和 length 属性之外,exec() 方法还返回两个属性。
index 属性声明的是匹配文本的第一个字符的位置
input 属性则存放的是被检索的字符串 string。

我们可以看得出,在调用非全局的 RegExp 对象的 exec() 方法时,返回的数组与调用方法 String.match() 返回的数组是相同的。

但是,当 RegExpObject 是一个全局正则表达式时,exec() 的行为就稍微复杂一些。它会在 RegExpObject 的 lastIndex 属性指定的字符处开始检索字符串 string。当 exec() 找到了与表达式相匹配的文本时,在匹配后,它将把 RegExpObject 的 lastIndex 属性设置为匹配文本的最后一个字符的下一个位置。这就是说,您可以通过反复调用 exec() 方法来遍历字符串中的所有匹配文本。当 exec() 再也找不到匹配的文本时,它将返回 null,并把 lastIndex 属性重置为 0。

  1. var str = "Visit jay jay jay jay";
  2. var patt = /jay/g;
  3. var result;
  4. while ((result = patt.exec(str)) != null) {
  5. console.log(result);
  6. console.log("<br />");
  7. console.log(patt.lastIndex);
  8. }
  9. // 输出: 查找了 4次
  10. // [ 'jay', index: 6, input: 'Visit jay jay jay jay' ]
  11. // <br />
  12. // 9
  13. // [ 'jay', index: 10, input: 'Visit jay jay jay jay' ]
  14. // <br />
  15. // 13
  16. // [ 'jay', index: 15, input: 'Visit jay jay jay jay' ]
  17. // <br />
  18. // 18
  19. // [ 'jay', index: 19, input: 'Visit jay jay jay jay' ]
  20. // <br />
  21. // 22

提示:如果在一个字符串中完成了一次模式匹配之后要开始检索新的字符串,就必须手动地把 lastIndex 属性重置为 0
**

2、?

非贪婪匹配:
? 跟在量词后面,尽可能少的匹配,一旦匹配成功就不继续往下匹配:

  1. var str = "<div>,<p>,<h1>,<span>,</span>,</h1>,</p>,</div>";
  2. // 注意这里有两个 ? ,第一个问号表示出现 0 或 1次,第二个表示非贪婪匹配
  3. var reg1 = /<(\/?).*?>/g;
  4. var newStr = str.replace(reg1, "<$1p>");
  5. console.log(newStr); //<p>,<p>,<p>,<p>,</p>,</p>,</p>,</p>
  6. //如果没有后面那个 ? ,则会一次性匹配完,然后整个替换掉
  7. var reg2 = /<(\/?).*>/g;
  8. newStr = str.replace(reg2, "<$1p>");
  9. console.log(newStr); // <p>

前瞻表达式(不捕获)。

正则从头向尾匹配,往尾部的方向就是向前。

(?=exp) 正向前瞻 匹配后面满足(=可理解为等于)表达式exp的位置。

  1. var str = "ab ac ad";
  2. var reg = /a(?=d)/g;
  3. // 下面的表达式意思是:全局匹配 a 后面紧跟着 d 的所有 a ,并将匹配到的 a 替换成大写的 A
  4. var newStr = str.replace(reg, "A");
  5. console.log(newStr); // ab ac Ad 只有 ad 前面的 a 被替换成了大写 A

(?!exp) 负向前瞻 匹配后面不满足(!可理解为非)表达式exp的位置

  1. var str = "ab ac ad";
  2. var reg = /a(?!d)/g;
  3. // 下面表达式的意思:全局匹配 a ,并且 a 的后面不能紧跟 d ,满足的有 ab ac,并把匹配的 a 替换成 A
  4. var newStr = str.replace(reg, "A");
  5. console.log(newStr); // Ab Ac ad

前瞻,表示向前匹配,后面的只是一个条件而已。记得前瞻表达式不具有捕获特性。$n 这样的是不能用的。前瞻表达式还有另一个特性,就是不占位,前瞻字符本身不会匹配。
比如:

  1. var str = "Hello, Hi, I am Handsome Hilary.";
  2. var reg = /H(?!i)e/g;
  3. var newStr = str.replace(reg, "T");
  4. console.log(newStr); //Tllo, Hi, I am Handsome Hilary.

注意观察输出的字符串,前瞻的作用仅仅是匹配出满足前瞻条件的字符”H”,匹配出了”Hello”和”Handsome”当中的H,但同时前瞻表达式本身不会匹配,不占位置,接下来还是会紧接着”H”开始继续往下匹配,这时候匹配条件是”e”,于是”Hello”中的”He”就匹配成功了,而”Handsome”中的”Ha”则匹配失败。

3、test

  1. // 注意这里是带 g 全局标记
  2. var reg = /\d/g
  3. var n = 12
  4. reg.test(n) // true
  5. // lastIndex 表示下一个开始匹配的位置
  6. reg.lastIndex // 1
  7. reg.test(n) // true
  8. reg.lastIndex // 2
  9. reg.test(n) // false
  10. reg.lastIndex // 0
  11. // 循环从头开始
  12. reg.test(n) // true
  13. reg.lastIndex // 1

如上代码,带上全局的test,可以一直循环匹配。匹配到底后,lastIndex会重置为0。跟 test 类似,exec 方法也是:

  1. // 注意这里是带 g 全局标记
  2. var reg = /\d/g
  3. var n = 12
  4. reg.exec(n)
  5. // 1 表示匹配到的字符,index:表示开始匹配的位置,input 表示源字符
  6. // ["1", index: 0, input: "12", groups: undefined]
  7. reg.exec(n)
  8. // ["2", index: 1, input: "12", groups: undefined]
  9. reg.exec(n)
  10. // null

4、使用正则匹配路由

  1. let str = '/article/9/jay';
  2. let param = '/article/:age/:name';
  3. // 先将age,和age提取出来
  4. let keys = [];
  5. // 返回一个正则字符串,是为了能提取 9 jay
  6. let regStr = param.replace(/:([^\/]+)/g,function () {
  7. keys.push(arguments[1]);
  8. return '([^\/]+)'
  9. });
  10. let reg = new RegExp(regStr);
  11. let arr = str.match(reg);
  12. console.log(arr.slice(1)); // ['9','jay']
  13. console.log(keys); // ['age','name']