正则表达式一般用来匹配字符串模版。
1. 表示方式
正则表达式有两种表示方式。下面两种方式调用的时候,都相当于新建了一个正则表达式。
1. RegExp对象表示法(知道就行)
new RegExp(‘a‘,‘i‘); //相当于/a/i // 这种表示法的特殊之处在于,第一个参数是字符串,对于\的处理,需要转译 new RegExp(‘\\+a‘,‘i‘); // 相当于/\+a/i // 另外第一个参数也可以直接写另一种正则表达式 new RegExp(/a/i); // 相当于/a/i的拷贝,ES5中不允许有第二个参数 // ES6中可以有第二个参数 new RegExp(/a/ig,‘i‘); // 可相当于/a/i,第二个参数覆盖第一个参数的修饰符
2. 斜杠开始和结束(用这个)
因为这个写法在编译阶段就新建一个正则表达式,效率更高,也更直观。
/a/i
2. 实例属性
实例属性基本对应了正则表示式的修饰符,只有lastIndex是可写属性,其他都是只读属性。
在原型对象上的属性。
1.修饰符属性
只有u修饰符可以识别大于0xFFFF的字符,其他的修饰符都不行!
1.RegExp.prototype.ignoreCase对应i修饰符,忽略大小写
var reg = /xyz/i; reg.test(‘XYZ‘); // true reg.ignoreCase; // true
2.RegExp.prototype.global对应g修饰符,全局匹配
var regG = /x/g; var reg = /x/; ‘x-x-x‘.replace(regG,‘y‘); //‘y-y-y‘ ‘x-x-x‘.replace(reg,‘y‘); // y-x-x regG.global;// true
3.RegExp.prototype.multiline对应m修饰符
使位置字符(^,$)可以匹配行终止符(/r,/n,\u2028行分隔符,\u2029段分隔符)
var reg = /^test$/; var regM = /^test$/m; reg.test(‘test\n‘); // false regM.test(‘\rtest\n‘); // true regM.test(‘\u2028test\u2029‘);// true regM.multiline; //true
4.RegExp.prototype.unicode ES6 对应u修饰符,匹配大于0xFFFF的字符。
1)当同时使用u修饰符,其他修饰符也可以识别四个字节的字符,当成一个字符
var str = ‘??‘; var reg = /^.$/; var regU = /^.$/u; reg.test(str); // fasle 将其处理成两个字符,不匹配一个字符的正则表达式 regU.test(str); // true 识别成一个字符 regU.unicode; //true // 量词,匹配识别成两个字符后的第二个字符 /??{2}/.test(‘????‘); // false /??{2}/u.test(‘????‘); // true // 字符形式一样,字符编码不同,如‘\u004B‘,‘\u212A‘都表示大写K (/[a-z]/i).test(‘\u004b‘);//true 只能识别ASCII码为75的K (/[a-z]/i).test(‘\u212A‘); // false (/[a-z]/iu).test(‘\u004b‘); // true (/[a-z]/iu).test(‘\u212A‘); // true
2)可以识别unicode字符的大括号表示法
var reg = /\u{61}/; //相当于匹配反斜杠和61个u var regU = /\u{61}/u; //相当于码点0x61 == 97 reg.test(‘\\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu‘); //true regU.test(‘\u{61}‘); // true regU.test(‘a‘); // true
3)无效的转译会报错
var reg=/\,/; var regU=/\,/u; reg.test(‘,‘);// true \无效 regU.test(‘,‘); // 报错,Invalid escape
5.RegExp.prototype.sticky ES6 对应y修饰符,test,exec方法中基本和g一致。有两点重要区别
1)y修饰符有“粘连”属性,就是每次开始匹配位置的值就必须符合匹配规则
var regY = /a/y; var regG = /a/g; regY.lastIndex; //0 regY.test(‘_a_a_a‘);// false 位置0的字符不符合匹配规则 regG.lastIndex; //0 regG.test(‘_a_a_a‘); // true
2)在字符串匹配方法中,y修饰符只返回第一个匹配结果,想返回所有的需要配合g修饰符
var regY = /a/y; var regG = /a/g; var str = ‘a_a_‘; str.match(regY); // [‘a‘] str.match(regG); // [‘a‘,‘a‘] str.replace(regY,‘y‘); // ‘a_a_‘ 第一次不替换 str.replace(regY,‘y‘); // ‘y_a_‘ 第二次替换 str.replace(regG,‘y‘); //‘y_y_‘
6.RegExp.prototype.dotAll ES2018 对应s修饰符,使元字符(.)可以匹配任意字符
即可以匹配“行终止符”
var reg=/^.$/; var regS = /^.$/s; reg.test(‘\n‘); //false regS.test(‘\n‘); //true regS.dotAll; //true
2. 其他属性
1. RegExp.prototype.lastIndex属性--可写属性
主要配合test,exex使用,用于查找或者设置查询起始位置
该属性起作用,主要在使用了g修饰符时。
2. RegExp.prototype.source属性--返回正则表达式内容
(/[a-z]/g).source;// "[a-z]" 除了//之外的字符串
3. RegExp.prototype.flags属性--返回使用过的修饰符
(/[a-z]/ig).flags; //‘gi‘
3. 实例方法
1. RegExp.prototype.test()
返回布尔值,表示是否匹配成功。
如果使用g修饰符,同一个表达式每次匹配都从上一次匹配结束的位置开始。
如果不使用g修饰符,则每次都从开始位置匹配。匹配位置可以用lastIndex表示。
var reg = /a/; var regG = /a/g; reg.lastIndex; // 0 reg.test(‘a_a_‘); // true reg.lastIndex; // 0 reg.test(‘a_a_‘); // true regG.lastIndex;// 0 regG.test(‘a_a_‘); // true regG.lastIndex;// 1 regG.test(‘a_a_‘); // true
还可以设置lastIndex的值来指定开始匹配的位置。
var regG = /a/g; regG.lastIndex = 3; regG.test(‘aabc‘); // false
2.RegExp.prototype.exec()
返回数组。返回匹配结果,包含组匹配。
和test类似。如果使用g修饰符,每次从上次匹配结束位置后开始。
var regG = /a/g; regG.exec(‘a_a_‘); // ["a"]
4. 元字符
在正则表达式中代表特殊含义的字符叫做“元字符”。
这些字符如果要匹配本身,需要加上转译字符,如\.,表示点
1.点字符(.)
代表除了“行终止符(\r\n\u2088\u2089)”之外的所有字符。
2.位置字符(^ $)
^代表起始字符;$代表终止字符
/^test$/.test(‘test‘); // true 只能有一个test
3. 选择字符(|)
选择字符表示“或关系”,包括符号前后的多个字符
/fred|Berry/.test(‘fred‘); // true
4.字符类字符([])
表示只要匹配[]中的一个字符就可以了。
/[xyz]/.test(‘x‘); //true
字符类有两个特殊字符。这两个特殊字符在字符类之外,按照普通字符解释
1)脱字符(^)
表示否定关系。只能用在[]起始位置。[^]表示所有字符
/[^a-z]/.test(‘A‘); //true 匹配所有不是a-z的字符
2)连字符(-)
表示连续的字符。只在[]内表示该含义。
/[1-31]/.test(1);// true 表示1-3和1,匹配任意一个 /1-31/.test(‘1-31‘); // true
5. 重复类({ })
表示字符重复的个数。这个类只作用于前面的一个字符。
{n}--n次 {n,m} -- 重复n-m次 {n,}--至少重复n次
/lo{2}k/.test(‘look‘); //true
6. 量词符--出现0或者1次(?)
相当于{0,1}
/a?/.test(‘‘); //true
7.量词符--出现0或者多次(*)
相当于{0,}; 默认贪婪匹配,匹配到不符合规则结束;
可以和?一起,表示非贪婪模式(*?),匹配0个成功就结束
/a*/.exec(‘aaaabc‘); // [‘aaaa‘] /a*?/.exec(‘aaaabc‘); // [""] 出现0次
8. 量词符--出现1或者多次(+)
相当于{1,},默认贪婪匹配。
可以和?一起,表示非贪婪模式(+?),匹配一个成功就结束
/a+/.exec(‘aaaabc‘); // [‘aaaa‘] /a+?/.exec(‘aaaabc‘); //[‘a‘]
9. 反斜杠(\\)
表示反斜杆,一个表示转译
10. 组匹配(())
1)含义
组匹配可以匹配分组的内容,并捕获括号内的匹配。
/fred+/.test(‘freddddd‘); // true /(fred)+/.test(‘fredfred‘); // true
组匹配一般不和g修饰符一起,如果想要一起,可以遍历exec实现;或者matchAll
‘abc‘.match(/(.)b(.)/g); // ["abc"] 不返回组匹配
在正则表达式中,可以使用\N,即\加上一个数字,来表示匹配的第N个组匹配。
应用:用于html标签匹配
/(.)b(.)\1b\2/.test(‘abcabc‘); // true // 如果有括号嵌套,外层括号是\1,内层括号是\2
ES2018引入了具名组匹配。具名组匹配不需要考虑组匹配的顺序。
即给组匹配指定了变量名,相当于key值,表示<?name>
只要使用了具名组匹配,在匹配结果的groups属性上就会有变量名。
一般match和exec的方法的匹配结果含有groups属性。
var reg = /(\d{4})-(\d{2})-(\d{2})/; var regName=/(?<year>\d{4})-(?<month>\d{2})-(?<date>\d{2})/; ‘1999-12-31‘.match(reg).groups; // undefined ‘1999-12-31‘.match(regName).groups; // {date: "31",month: "12",year: "1999"} reg.exec(‘1999-12-31‘).groups; // undefined regName.exec(‘1999-12-31‘).groups; // {date: "31",year: "1999"}
正则表达式中,具名组匹配可以用\k<组名>来表示某个组匹配。和\N性质类似。
2)非捕获组匹配(?:XXX)
组匹配中加入?:符号,表示该组匹配不返回。不能和具名组匹配一起使用。
var regName=/(?:\d{4})-(\d{2})-(\d{2})/; regName.exec(‘1999-12-31‘); // [‘1999-12-31‘,‘12‘,‘31‘]
3)先行断言(X(?=Y))
X只有在Y前面才匹配。返回匹配的X的值,不返回Y。
/\d(?=%)/.exec(‘he 100%‘); // ["100"]
4) 先行否定断言(X(?!Y))
X只有不在Y的前面才匹配。返回X的值,不返回Y。
/\d(?!%)/.exec(‘this\‘s 50 that\‘s 80%‘); //["5"] \d只表示一个数字
5)ES2018后行断言((?<=Y)X)
X只有在Y的后面才匹配。而且后行断言,从右到左运行。
即右结合运算符。另外还有=,?:也是右结合运算符。
/(?<=(\d+))(\d+)/.exec(‘hehe 12343‘); // ["2343","1","2343"] 右结合 /(\d+)(\d+)/.exec(‘hehe 12343‘); // [‘12343‘,‘1234‘,‘3‘]
5. 预定义模式
1)\d---[0-9] 数字
2)\D---[^0-9] 非数字
3)\w---[A-Za-z0-9_] 字母、数字、下划线
4)\W---[^A-Za-z0-9_]非字母、数字、下划线
5)\s---[ \r\n\f\t\v] 空白字符: 空格、制表符、终止符
6)\S---[^ \r\n\f\t\v] 非空白字符
7)\b---词的边界
8)\B---词非边界
ES2018
9)\p{...}---匹配某种属性的所有字符
(/\p{Script=Greek}/u).test(‘π‘);// 匹配希腊字体 (/\p{Number}/u).test(‘???‘); // 匹配各种数字
10)\P{...}---不满足匹配的某种属性