1、 $1 和\1 是什么,怎么用?
\1 和 $1 都是代表表达式中()所匹配到的内容,只不过\1用于表达式内,$1则用于表达式外
举个栗子:
/(123)(456)\1\2/ 中\1 代表第一个()内的内容,也就是123,\2代表第二个括号内的内容,为456,表达式就类似于/(123)(456)123456/ 能匹配到 123456123456
'123456'.replace(/(123)(456)/,'$1.....$2') 其中$1对应123,$2对应456,得到的结果就是123.....456
2、正则表达式引擎
正则表达式引擎区分为DFA和NFA。
DFA是文本主导型匹配,也就是从匹配文本入手,从左往右匹配表达式,每个字符只会被匹配一次,很快,但是很多特性比如捕获组之类的,都不支持。不是主流的方法
NFA则是 正则表达式主导型匹配,从表达式入手,去依次匹配。
let str = 'abc'
let reg = /ab{1,3}c/
重点在第三部,黄色代表没有匹配上,这是因为正则默认是贪婪匹配,它会试图去匹配最多的次数,在第三步b{1,3}试图去寻找b,可是却出现了c,因此需要回溯到上一个位置重新匹配。
3、回溯
再举一个栗子:
/12(3|4)/.test(125124)
按照NFA原则,我们根据表达式入手,1先对应上了文本的1,然后2也对应上了文本的2,但是再找下去,发现5不满足3|4中的3,然后回溯到2的位置,去尝试匹配3|4,5也不满足3|4中的4,因此失败,这时候就会回溯到这125124中的2,发现2不等于/12(3|4)/,然后5。。。。。以此类推,直到匹配结束。
回溯就是一个表达式不满足现在字符就不停回退尝试直到找出符合条件的为止,因此当一个表达式很长很不确定时,就有可能会引起不停的回溯尝试,从而引发性能问题。
4、位置指定
盗图:
Q:"<a top:10px,left:10px;/><b top:20px;left:34px/>" 取得中间的top,left
A:/(?<=top:)([0-9]+)|(?<=left:)[0-9]+/g
//(?<=top:)代表要找到在top:右边的内容,但是不会匹配到top:这一串内容。
5、回溯与?<=
(/(?<=(\d)\d*)\1/).test('9878') 会得到什么?
上面这个表达式,若是按照之前的思路,从9开始一个一个匹配,最终理想的情况是能匹配到878的,但是实际结果确实false?
分析一下:
(?<=(\d)\d*)是位置指定,在这之中 *代表贪婪匹配,当两者到了一块,就不会引发回溯。过程如下:
1、\d匹配9,\d*贪婪匹配878,\1为9,失败,无回溯
2、\d匹配8,\d*贪婪匹配78,\1为8,失败,无回溯
3、\d匹配7,\d*贪婪匹配8,\1为7,失败,无回溯
4、\d匹配8,\d*贪婪匹配空,\1 为8,失败,
那如果想要匹配到878该怎么办?很简单,不要将贪婪或者惰性匹配放到位置指定的括号里。。。比如: /(?<=(\d))\d*\1/ 过程如下:
1、\d匹配9,\d*贪婪匹配878,\1为9,失败,回溯
2、\d匹配9,\d*贪婪匹配87,\1为9,失败,回溯
3、\d匹配9,\d*贪婪匹配8,\1为9,失败,右移一位
4、\d匹配8,\d*贪婪匹配78,\1为8,失败,回溯
5、\d匹配8,\d*贪婪匹配7,\1为8,成功
不仅贪婪匹配会如此,惰性匹配也会如此,当将上面的*变成*?,(/(?<=(\d)\d*?)\1/).test('9878') 结果会是什么?,当然是false了,惰性匹配会匹配最少的字符,也就是说\d*永远匹配到的是空,过程如下:
1、\d匹配9,\d*?惰性匹配为空,\1为9,失败,右移一位
2、\d匹配8,\d*?惰性匹配为空,\1为8,失败,右移一位
3、\d匹配7,\d*?惰性匹配为空,\1为7,失败,右移一位
4、\d匹配8,\d*?惰性匹配为空,\1 为8,失败
同理,想要匹配成功,正确的表达式应该是(/(?<=(\d))\d*?\1/).test('9878')过程如下:
1、\d匹配9,\d*?惰性匹配空,\1为9,失败,回溯
2、\d匹配9,\d*?惰性匹配8,\1为9,失败,回溯
3、\d匹配9,\d*?惰性匹配87,\1为9,失败,回溯
4、\d匹配9,\d*?惰性匹配878,\1为9,失败,右移一位
5、\d匹配8,\d*?惰性匹配空,\1为8,失败,回溯
6、\d匹配8,\d*?惰性匹配7,\1为8,成功
6、表达式符号
1、*表示匹配前面的字符0个或多个
2、+表示前面的字符1个或多个
3、?表内示放在其他字符后面表容示前面的字符可以有,也可以没有,或者放在*、+后面表示匹配尽可能少的字符
例如:字符串fooooo,正则fo*和fo+会匹配整个字符串,
fo+? 匹配fo,
fo*? 匹配f
4、*+没有这样的用法,除非是匹配星号本身,即: \*+ 表示一个或多个星号
参考资料:
1、zhidao.baidu.com/question/18…
2、www.cnblogs.com/whaozl/p/54…
3、blog.csdn.net/weixin_4251…
4、www.qiutianaimeili.com/html/page/2…
5、www.cnblogs.com/gddcz/p/913…