公司的小伙伴希望能讲一下正则表达式,于是趁着这个机会自己也把正则表达式的重新学习了一下,由于不同语言对正则表达式提供了不同的方法支持,以下所有的正则测试均基于Javascript
1. 元字符
正则表达式中的字符可以认为有两类,一类被称为元字符,代表的是有在正则表达式中有特殊含义的字符,另一类就是普通字符。
个人认为元字符分为了三类:固有语义,简写字符集和分组匹配
1.1 固有语义的字符
1.1.1 选择字符
选择字符有两种[]
和[^]
,[]
表示匹配结果包含[]
中的任意字符,[^]
则表示匹配结果不能包含[^]
中的字符
/[1234]/.test('1'); // true
/[1234]/.test('5'); // false
/[^1234]/.test('2'); // false
/[^1234]/.test('5'); // true
需要注意的是[]
和[^]
中的字符,除开部分特殊字符外(例如:[
,]
,-
等),都是自带转义属性。也就是说[]
中的字符都不再具有特殊意义
// 在正则中‘.’是任意匹配的意思,但是[]中失去了其本来的意义
/./.test(1); // true
/[.]/.test(1); // false
/[.]/.test('.'); // true
1.1.2 重复字符
表示一个字符出现次数包括:?
, *
, +
, {m, n}
// 0次或1次匹配
/[a]?/.test('a'); // true
/[a]?/.test('b'); // true
// 0次或多次匹配
/[a]*/.test('a'); // true
/[a]*/.test('b'); // true
// 1次或多次匹配
/[a]+/.test('a'); // true
/[a]+/.test('b'); // false
// 出现m到n次
/[a]{2,3}/.test('aab'); // true
/[a]{2,3}/.test('abab'); // false
1.1.3 锚点字符
有表示开始的^
和表示结束的$
,用于限制正则匹配的开始和结束
/[1]/.test('12'); // true
// 以1开头
/^[1]/.test('21'); // false
/^[1]/.test('12'); // true
// 以1结尾
/[1]$/.test('12'); // false
/[1]$/.test('21'); // true
1.1.4 转义字符
使用\
来进行将一些元字符进行转义,从而使得元字符可以进行匹配
/[]/.test('[]'); // false
/\[\]/.test('[]'); // true
1.1.5 通配字符
使用.
来匹配任意字符,只要匹配字符串不为空匹配结果都为真
/./.test('a-1sd'); // true
1.1.6 或字符
使用|
来对多个字符取并集匹配
/1|2/.test('1'); // true, 等价于/[12]/.test('1')
/1|2/.test('2'); // true, 等价于/[12]/.test('1')
/The|to/.test('to'); // true
1.1.7 非贪婪匹配
在重复字符后面使用?
来进行非贪婪匹配,非贪婪匹配是指在匹配字符对时候尽可能少的匹配
// 使用replace函数来验证
'aaab'.replace(/[a]+/g, '='); // =b
'aaab'.replace(/[a]+?/g, '='); // ===b
上面的例子中:
第一个使用了贪婪模式,因此\[a]+\
将匹配aaa
,因此执行替换的时候将aaa
替换为了=
第二个使用了非贪婪匹配,因此\[a]+?\
将分别匹配每个a
,因此最后将每个a
分别替换为=
,aaa
就变为===
1.2 简写字符集
将一些字符,和转义符号配合使用,可以得到一些正则表达式默认匹配范围
1.2.1 字符数字匹配集
使用\w
可以匹配字符数字,相当于[a-zA-Z0-9_]
,而\W
匹配所有非字符数字,相当于[^a-zA-Z0-9_]
/\w/.test('1'); // true
/\W/.test('1'); // false
1.2.2 数字匹配集
使用\d
匹配数字,相当于[0-9]
,同样\D
匹配非数字,相当于[^0-9]
/\d/.test('1'); // true
/\D/.test('1'); // false
1.2.3 空格匹配集
使用\s
匹配空格,相当于[ ]
,使用\S
匹配非空格,相当于[^ ]
/\s/.test(' '); // true
/\S/.test(' '); // false
1.2.4 其他
其他还包括换行符匹配\n
,回车匹配\r
,制表符匹配\t
等
1.3 分组
正则表达式中可以将匹配进行分组,并可以分别获取匹配的分组,同时表达式中也可以指定分组的引用
1.3.1 分组匹配
使用()
可以将正则表达式进行分组
/(The)|(To)/.test('The'); // true
看上去和之前的差不多,但是,这里可以在正则表达式中,利用捕获模式(/ + 数字
)和替换模式($ + 数字
)获取,获得对应分组的引用,分组的计数是从1开始的
// 捕获模式
/(The)(To)\1/.test('TheTo'); // false
/(The)(To)\1/.test('TheToThe'); // true
/(The|To)\1/.test('TheThe'); // true
/(The|To)\1/.test('ToTo'); // true
/(The|To)\1/.test('TheTo'); // false
// 替换模式
'TheTo'.replace(/(The)(To)/, '$2$1') // ToThe
1.3.2 非获取匹配
在分组匹配中,可以使用(?)
的方式,来进行匹配,但是匹配后不进行存储使用,也就是不能使用捕获模式和替换模式的方式获取到分组信息
1.3.2.1 匹配不获取
使用(?:)
去匹配字符,通常和|
来组合使用
/Test(?:er|or)/.test('Tester'); // true
/Test(?:er|or)/.test('Testor'); // true
/Test(er|or)\1/.test('Testerer'); // true
/Test(er|or)\1/.test('Testoror'); // true
/Test(?:er|or)\1/.test('Testeror'); // false
/Test(?:er|or)\1/.test('Tester\1'); // true
1.3.2.2 正向预查匹配
使用(?=)
来进行正向匹配,匹配字符串开始处进行查找
/Windows(?=2000|3000)/.test('Windows3000'); // true
/Windows(?=2000|3000)/.test('Windows4000'); // false
1.3.2.3 正向预查不匹配
使用(?!)
来进行匹配和(?=)
刚好相反
/Windows(?!2000|3000)/.test('Windows3000'); // false
/Windows(?!2000|3000)/.test('Windows4000'); // true
1.3.2.4 反向预查匹配
使用(?<=)
来进行匹配
/(?<=2000|3000)Windows/.test('3000Windows'); // true
/(?<=2000|3000)Windows/.test('4000Windows'); // false
1.3.2.4 反向预查不匹配
使用(?<!)
来进行匹配,和(?<=)
相反
/(?<!2000|3000)Windows/.test('3000Windows'); // false
/(?<!2000|3000)Windows/.test('4000Windows'); // true
2. 匹配模式
常用的匹配模式有三个:i
, g
, m
,不同的语言支持的匹配模式的会有所不同
2.1 忽略大小匹配
使用i
做为匹配模式,可以忽略匹配中的大小写
/[A]/.test('a'); // false
/[A]/i.test('a'); // true
2.2 全局匹配
使用g
做为匹配模式,可以匹配字符串中的所有字符,而不是第一个字符
'abcabcabc'.replace(/[a]/, '='); // =bcabcabc
'abcabcabc'.replace(/[a]/g, '='); // =bc=bc=bc
2.2 多行匹配
使用m
做为匹配模式,可以匹配多行字符,通常和g
一起使用
3. Javascript支持正则的方法
3.1 支持的方法
各语言都提供了各种支持正则都方法,Javascript以下方法都支持正则表达式的使用:
RegExp.prototype.exec()
RegExp.prototype.test()
String.prototype.replace()
3.2 lastIndex
Javascript中,在正则表达式对象存在lastIndex
属性,每进行一次匹配,这个属性会进行更新为当前匹配位置,并以在下一次匹配时,以这个位置开始进行匹配
let str = 'abc';
let reg = /[a]/g;
reg.test(str); // true
console.log(reg.lastIndex); // 1
reg.test(str); // false
// 由于匹配失败,所以会被重置为0
console.log(reg.lastIndex); // 0
4. 总结
正则表达式的识别主要是区别元符号和普通符号的,同时注意转义符号的使用特点,读懂正则表达式就不难了。
网友评论