Fork me on GitHub

正则表达式进阶

关于分组

分组在正则中用的还是比较广的,我所理解的分组 就是一对括号() ,每一对括号 就代表了一个分组,分组可以分为:捕获性分组和非捕获性分组

捕获性分组

关于捕获性分组

字面意思就是可以捕获的分组类型,比如

1
2
3
console.log(/(\d)(-)/.test('1-'))//true
console.log(RegExp.$1) //1
console.log(RegExp.$2) //-

捕获性分组会在 比如$1, match exec这样的函数中以第二项,第三项的形式得到相应分组的结果

案例

1
2
3
4
5
// var reg = /test(\d+)/;
var reg = /test(\d+)/g;
var str = 'new test001 test002';
console.log(str.match(reg)); //["test001", "001", index: 4, input: "new test001 test002"]
console.dir(RegExp)

非捕获性分组–(?:)

非捕获性分组也就是 有些地方需要用到一对括号,但是又不想让他成为一个捕获性分组也就是不想让这个分组被类似 macth exec 这样的函数所获取到通常在括号内部的前面加上?: 也就是 (?:pattern)这样就变成了一个非捕获性分组,比如

1
2
3
console.log(/(\d)(?:-)/.test('1-')) //true
console.log(RegExp.$1)//1
console.log(RegExp.$2)//空值

非捕获性分组–断言

javascript只支持零宽先行断言,所以关于JS中的正则表达式的断言,说的一般就是零宽,
而零宽先行断言又可以分为正向零宽先行断言,和负向零宽先行断言。

零宽度断言

零宽断言正如它的名字一样,是一种零宽度的匹配,它匹配到的内容不会保存到匹配结果中去,最终匹配结果只是一个位置而已。

作用是给指定位置添加一个限定条件,用来规定此位置之前或者之后的字符必须满足限定条件才能使正则中的字表达式匹配成功。

正向零宽断言

代表符号

符号:?=

案例解析

  1. 简单了解
1
2
3
4
var str = "abZW863";
var reg = /ab(?=[A-Z])/;
console.log(str.match(reg));
// "ab"

在以上代码中,正则表达式的语义是:匹配后面跟随任意一个大写字母的字符串”ab”。最终匹配结果是”ab”,因为零宽断言”(?=[A-Z])”并不匹配任何字符,只是用来规定当前位置的后面必须是一个大写字母。

  1. 案例进阶

如果在上述案例的基础上我想要匹配上ZW应该怎么写;

1
2
3
4
var str = "abZW863";
var reg = /ab(?=[A-Z]+)[A-Z]+/;
console.log(str.match(reg));
//"abZW"
  1. 案例3
1
2
3
4
var str="<div>antzone";
var reg=/^(?=<)<[^>]+>\w+/;
console.log(str.match(reg));
//"<div>antzone"

解析过程:

  • 首先^符号表示位置,从0开始匹配,匹配成功,让后将控制权交给(?=<)
  • 由于^是零宽度,所以(?=<)还是从0开始匹配,要求第一个位置的必须是<,所以也成功
  • 由于(?=<)也是零宽度,<还是从0开始匹配,第一个<成功;
  • 后面就没啥好说的了;

负向零宽断言

代表符号

符号:?!

案例解析

  1. 案例1
1
2
3
4
var str = "abZW863";
var reg = /ab(?![A-Z])/;
console.log(str.match(reg));
// null

正则表达式的语义是:匹配后面不跟随任意一个大写字母的字符串”ab”。正则表达式没能匹配任何字符,因为在字符串中,ab的后面跟随有大写字母。

  1. 案例2
1
2
3
var str="abZW863ab88";
var reg=/ab(?![A-Z])/g;
console.log(str.match(reg));
  • 首先由正则表达式的字符”a”获取控制权,从位置0处开始匹配,匹配字符”a”成功
  • 然后控制权转交给”b”,从位置1处开始匹配,配字符”b”成功,然后控制权转交给”(?[A-Z])”,它从位置2处开始匹配,它要求所在位置的右边不能够是任意一个大写字母,而位置的右边是大写字母”Z”,匹配失败
  • 然后控制权又重新交给字符”a”,并从位置1处开始尝试,匹配失败,然后控制权再次交给字符”a”,从位置2处开始尝试匹配
  • 依然失败,如此往复尝试,直到从位置7处开始尝试匹配成功,然后将控制权转交给”b”,然后从位置8处开始尝试匹配,匹配成功,然后再将控制权转交给”(?[A-Z])”,它从位置9处开始尝试匹配,它规定它所在的位置右边不能够是大写字母,匹配成功,但是它并不会真正匹配ab后面的字符,所以最终匹配结果是”ab”。
  1. 案例3
1
var reg = /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,12}$/;

关于贪婪模式和非贪婪模式

介绍

贪婪与非贪婪模式影响的是被量词修饰的子表达式的匹配行为,贪婪模式在整个表达式匹配成功的前提下,尽可能多的匹配,而非贪婪模式在整个表达式匹配成功的前提下,尽可能少的匹配。非贪婪模式只被部分NFA引擎所支持。

属于贪婪模式的量词,也叫做匹配优先量词,包括:

“{m,n}”、“{m,}”、“?”、“*”和“+”。

在一些使用NFA引擎的语言中,在匹配优先量词后加上“?”,即变成属于非贪婪模式的量词,也叫做忽略优先量词,包括:

“{m,n}?”、“{m,}?”、“??”、“*?”和“+?”。

案例

1
2
console.log('abcadc'.match(/a.+c/g)) //["abcadc"]
console.log('abcadc'.match(/a.+?c/g)) // ["abc", "adc"]