正则中的一些概念和js中与正则有关的一些api
特殊字符
特殊字符,可以代表某类字符。
- ^ 匹配字符串的开头
- $ 匹配字符串的结尾
- [] 匹配给定字符集中的一个字符
- a|b 匹配a或b,
- . 匹配除了换行符\n之外的任何字符;
- \s 匹配任意空白字符,等价于[\t\n\r\f\v]
- \S 匹配任意非空白字符,等价于[^\t\n\r\f\v]
- \w 匹配字母数字下划线,等价于[0-9a-zA-Z_]
- \W 匹配非字母数字及下划线,等价于[^0-9a-zA-Z_]
- \d 匹配任意一个数字,等价于[0-9]
- \D 匹配任意一个非数字,等价于[^0-9]
- \b 匹配边界
当要匹配 "." 时,因为 "." 字符在正则表达式中有特殊含义,所以需要对其进行转义形式 \.。
量词
量词,量词用来表示某一个字符的重复次数。
- * 匹配前一个表达式0次或多次,等价于{0,}
- + 匹配前一个表达式1次或多次,等价于{1,}
- ? 匹配前一个表达式0次或1次,等价于{0,1}
- {m,n} 匹配前一个表达式m至n次
- {m} 精确匹配前一个表达式m次
- {m,} 匹配前一个表达式至少m次
js正则引擎的默认匹配模式是贪婪模式,在正则表达式中当在 * + ? 后面紧跟一个 ? 时,会使匹配模式变成惰性模式,会匹配更少的字符。
字符集
字符集,字符集规定了可选的字符,通常表示为 []。
0到9之间的任意字符可以表示为 [0-9],在字符集里面,- 在两个字符之间,和两边的字符连在一起表示为两个字符之间的全部字符。
在字符集里面,"." 没有特殊含义。
值得注意的是在没有使用量词的情况下,在正则表达式中,一个字符集占用一个字符的位置,只是该位置的字符可能是字符集中的任意一个字符。如果要表示两个字符,在不适用量词的前提下,要使用两个字符集。
捕获组
捕获组就是把正则表达式中子表达式匹配的内容,保存到内存中以数字编号或显式命名的组里,方便后面引用,当然,这种引用既可以是在正则表达式内部也可以是在正则表达式外部。
在js中有两种捕获组,最简单的是普通捕获组,就像这样 (\d{4})-(\d{2})-(\d{2}),在匹配字符串 2019-08-31 的时候,正则引擎同时也会把捕获的分组 2019 08 31 保存起来。
在正则表达式内部,正则引擎提供了 \number(number为从1开始的数字) 这样的表达式来引用保存的捕获组。
var s1 = '2019-08-08'
var s2 = '2019-08-31'
var reg1 = /(\d{2})-(\d{2})-(\d{2})/
var reg2 = /(\d{2})-(\d{2})-\2/
reg1.test(s1) // true
reg1.test(s2) // true
reg2.test(s1) // true
reg2.test(s2) // false
在上面的代码中,正则表达式reg2的最后用 \2 引用了第二个捕获组,字符串s1 符合该正则表达式,但字符串s2不符合该正则表达式。
除了上面这种以外,还可以使用命名捕获组,与普通捕获组相比,命名捕获组在书写上添加了 ?<name> ,name 是这个捕获组的名称,在正则表达式内部可以使用 \k 来引命名捕获组。与普通捕获组相比,命名捕获组在语义上更加清晰,但也不可避免地使得正则表达式变得更长。
var s1 = '2019-08-08'
var s2 = '2019-08-31'
var reg1 = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
var reg2 = /(?<year>\d{4})-(?<month>\d{2})-\k<month>/
reg1.test(s1) // true
reg1.test(s2) // true
reg2.test(s1) // true
reg2.test(s2) // false
如果分组不需要捕获,则需要这样来写正则表达式 /(?:\d{4})/
js 正则相关API
在js中与正则有关的函数有5个,分别是 test、exec、match、replace、split。
1、test
reg.test(str),检测指定字符串是否可以符合正则表达式,如果符合则返回 true,否则返回 false。
2、exec
该方法用于检索字符串中的正则表达式的匹配。该函数的参数是一个字符串,该函数返回一个数组,其中存放匹配的结果。如果未找到匹配,则返回值为 null。
var s1 = '2019-08-08'
var reg1 = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
reg1.exec(s1)
3、match
该方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。返回的结果与 exec 函数的结果比较类似。 调用match之后,可以通过RegExp对象上的 $N(N为1到9的数字)属性,来访问到匹配到的捕获组。
4、replace
stringObject.replace(regexp/substr,replacement)
replace 函数用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。该方法接受两个参数,第一个参数可以是字符串或对象,第二个参数可以是字符串或函数。
当replace函数的第一个参数是字符串的时候,只会替换第一次匹配到的字符串。
当replace函数的第一个参数是正则表达式,第二个参数是字符串时,可以在字符串内引用捕获组,普通捕获组可以使用形如 $1 的来引用,命名捕获组必须要使用 $<name> 来使用。
replace函数的第二个参数是匿名函数时,每次匹配到对应的字符串,都会执行一次该匿名函数,该函数的参数是捕获到的内容。该匿名函数的返回值是replace函数的返回值,如果该匿名函数不返回任何值,则replace函数返回 undefined。
var s1 = '2019-08-08'
var reg1 = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
s1.replace('08','09') // "2019-09-08"
s1.replace(reg1,'$2-$3-$1') // "08-08-2019"
s1.replace(reg1,'$<month>-$<day>-$<year>') //"08-08-2019"
s1.replace(reg1, (...args) => {
return `${args[1]}.${args[2]}.${args[3]}`
}) // "2019.08.08"
5、split
split() 方法用于把一个字符串分割成字符串数组。
stringObject.split(separator,howmany)
separator 可以是正则表达式或字符串。
howmany 指定切割结果的长度。