正则表达式零宽断言:
零宽断言还有其他的名称,例如"环视"或者"预搜索"等等,不过这些都不是我们关注的重点。
一.基本概念:
零宽断言正如它的名字一样,是一种零宽度的匹配,它匹配到的内容不会保存到匹配结果中去,最终匹配结果只是一个位置而已。
零宽断言分为先行断言(前瞻断言)和后发断言(后瞻断言)
前瞻断言要求所在位置的右侧必须符合子表达式
后瞻断言要求所在位置的左侧必须符合子表达式
javascript只支持零宽先行断言。
零宽先行断言又可以分为正向零宽先行断言,和负向零宽先行断言。
代码实例如下:
正向零宽先行断言实例代码:
var str="abZW863";
var reg=/ab(?=[A-Z])/;
console.log(str.match(reg));
负向零宽先行断言实例代码:
var str="abZW863";
var reg=/ab(?![A-Z])/;
console.log(str.match(reg));
二.匹配原理:
上面代码只是用概念的方式介绍了零宽断言是如何匹配的。
下面就以匹配原理的方式分别介绍一下正向零宽断言和负向零宽断言是如何匹配的。
1.正向零宽先行断言:
2.负向零宽先行断言:
代码实例如下:
var str="abZW863ab88";
var reg=/ab(?![A-Z])/g;
console.log(str.match(reg));
匹配过程如下:
1、首先由正则表达式的字符"a"获取控制权,从位置0处开始匹配,匹配字符"a"成功,
2、然后控制权转交给"b",从位置1处开始匹配,配字符"b"成功
3、然后控制权转交给"(?![A-Z])",它从位置2处开始匹配,它要求所在位置的右边不能够是任意一个大写字母,而位置的右边是大写字母"Z",匹配失败,然后控制权又重新交给字符"a",并从位置1处开始尝试,匹配失败
4、然后控制权再次交给字符"a",从位置2处开始尝试匹配,依然失败
5、如此往复尝试,直到从位置7处开始尝试匹配成功,
6、然后将控制权转交给"b",然后从位置8处开始尝试匹配,匹配成功
7、然后再将控制权转交给"(?![A-Z])",它从位置9处开始尝试匹配,它规定它所在的位置右边不能够是大写字母,匹配成功,但是它并不会真正匹配ab后面的字符
8、所以最终匹配结果是"ab"。
3.零宽度正回顾后发断言(后瞻断言)(?<=exp)
4.零宽度负回顾后发断言(?<!exp)
断言自身出现的位置的前面能匹配表达式exp。比如\b\w+(?<=ing\b)会匹配以ing结尾的单词,例如在查找I am reading.时,它匹配reading。正则的匹配顺序并一定都是按从左到右的顺序进行的。后瞻断言的顺序就是先右后左。例如(js写法)
$m="/(?<=[\d])\d+$/";
$str="1053";
preg_match($m, $str,$match);
var_dump($match);//["053"]