正则表达-分组与引用
Opened this issue · 0 comments
cg24 commented
正则的一些基础概念就不做过多介绍
分组与反向引用
在正则表达式中可以使用小括号对正则表达式进行分组,如(...),也就是说把括号内的东西当成一个小组,一个单元。分组就是正则表达式中的子表达式。举个例子:
//如下模式即可以匹配java,也可以匹配javascript
//因为?表示的是出现0次或1次,如果一次不出现那么就匹配的是java
//由于script就是一个小组,后面的“?”会对整个小组起作用
var reg = /java(script)?/ ;
对于正则表达式的分组,在RegExp对象中会保存一个对分组的引用,称为反向引用,可以通过RegExp.$1,RegExp.$2...(貌似最多只有$9(可能是因为如果支持10以上的引用表达式中\10的含义不唯一),还有一个RegExp.$_表示匹配的整个结果)来取得相应的分组匹配结果,如果超过9个以上的分组,则$1-$9 对应最前面的9个分组
var str="aaaaaaaabaaa";
var reg=/(a)(a)(a)(a)(a)(a)(a)(a)(b)(a)(a)(a)/gi;
reg.test(str);
RegExp.$9;//"b"
RegExp.$_;//"aaaaaaaabaaa"
var str ='abcdefghijklmn';
var reg =/(a)(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)(l)(m)(n)/gi;
reg.test(str);
for(var i=1;i<10;i++){
console.log(RegExp['$'+i]);
}
//'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i'
在正则表达式中可以通过\n来匹配第n个分组的内容,常用于匹配重复字符或字符串的,例如:
var str = "AA Am 99";
var reg = /(\w)\1/g;//\1表示第一个分组
str.match(reg);//输出: ["AA", "99"]
分组序号定义规则
分组序号定义的规则是根据分组左括号出现的次序定义的,例如:
var reg = /((java)(script))/;
reg.test("javascript");
RegExp.$1;//"javascript"
RegExp.$2;//"java"
RegExp.$3;//"script"
同时在第n个分组中小于等于\n的都会被忽略,小于n的分组此时的值是不确定的,如果解析的话有可能进入死循环,例如:
'aaabbbcccdddeeefff'.match(/(([abc])\1)\2/g);//["aa", "bb", "cc"]
'aaabbbcccdddeeefff'.match(/((([abc])\1)\2)\3/g);//["aaa", "bbb", "ccc"]
非捕获性分组
以 (?:..) 产生的分组称为非捕获性分组,对于普通的分组,会在 RegExp对象上保留对分组的引用,如果不是需要在后续的匹配中用到对该分组的引用,则会造成内存的浪费。而使用非捕获性分组则不会产生对分组的引用,所以在平时使用分组时,如果不需要操作分组的引用,建议使用非捕获性分组例如:
var reg = /java(?:script)(test)/;
reg.test("javascripttest");
RegExp.$1;//"test"
零宽断言
零宽断言分为零宽预测先行断言和零宽回顾后发断言(术语好难记),JavaScript中只支持零宽预测先行断言,其中又分为正向零宽预测先行断言“(?=exp)”和负向回顾后发断言“(?!exp)”,正向零宽预测先行断言用来检查接下来的出现的是不是某个特定的字符集。而负向回顾后发断言是检查接下来的不应该出现的特定字符串集。零宽断言是不会被捕获的。
var str1 = "bedroom";
var str2 = "bedding";
var reBed = /(bed(?=room))/ //在捕获bed这个字符串时,先去看接下来的字符串是不是room
console.log(reBed.test(str1)); //true
console.log(RegExp.$1)//‘bed’
console.log(RegExp.$2 === "") //true
console.log(reBed.test(str2)) //false
var str1 = "bedroom";
var str2 = "bedding";
var reBed = /(bed(?!room))/ //要求它后面不能是room
console.log(reBed.test(str1))//false
console.log(reBed.test(str2))//true