正则表达式
Youky ... 2021-10-11 About 3 min
# 正则表达式
# 定义
用描述性的语言定义一个规则,并检验字符串是否符合规则。
创建方式有两种:
- 字面量创建
const reg1 = /\d/g;
1
- 构造函数创建。此时对于特殊字符
\
需要进行转义
const reg2 = new RegExp('\\d', 'g')
console.log(reg2) // /\d/g
1
2
2
# 匹配规则
# 特殊标记
\
:用于特殊字符的转义.
:匹配任何字符(除了换行符)^
:匹配的开头$
:匹配的结尾
# 转义
\n
:换行\s
:空格符(空格、回车、制表符等)\d
:数字\D
:非数字\w
:单字字符(数字、字母、下划线)
# 匹配次数
*
:任意次数+
:至少一次,等价于{1,}?
:0或1次,等价于{0,1}{n}
:n次{n,m}
:n到m次()包括n和m。若省略m则表示至少n次
# 匹配若干个元素
x|y
:匹配x或y[abc]
:匹配a、b、c中的任意一个[^abc]
:匹配不属于该集合的字符[0-9a-zA-Z_$]
:合法的变量名可用的字符
# 正则表达式的标志
标志 | 含义 |
---|---|
g | 全局匹配 |
i | 不区分大小写 |
m | 多行搜索 |
s | 允许. 匹配换行符 |
u | 使用Unicode模式进行匹配 |
y | 使用粘性搜索(每次从字符串的当前位置开始) |
全局匹配:当一次匹配结束时,下一次匹配从上一次的结束位置开始 eg:
const reg = /\d+/g
const str = '12a3'
console.log(reg.exec(str)) // [ '12', index: 0, input: '12a3', groups: undefined ]
console.log(reg.exec(str)) // [ '3', index: 3, input: '12a3', groups: undefined ]
1
2
3
4
2
3
4
而默认情况下是每次匹配都从头开始:
const reg = /\d+/
const str = '12a3'
console.log(reg.exec(str)) // [ '12', index: 0, input: '12a3', groups: undefined ]
console.log(reg.exec(str)) // [ '12', index: 0, input: '12a3', groups: undefined ]
1
2
3
4
2
3
4
粘性搜索:下次匹配必须从上一次终止的位置开始
const reg = /\d+/y
const str = '12a3'
console.log(reg.exec(str)) // [ '12', index: 0, input: '12a3', groups: undefined ]
console.log(reg.exec(str)) // null,因为下一次开始的index为2,对应的字符为a
1
2
3
4
2
3
4
# 匹配方法
# 判断字符串是否符合规范:reg.test
const str = '123@qq.com';
const reg = /^\d+@\w+\.com$/
console.log(reg.test(str)) // true
1
2
3
2
3
# 提取字符串内容并分组:reg.exec
reg.exec
方法返回的是一个数组,首项是字符串匹配成功了的部分,数组的剩下几项依次是匹配到的分组。
注意,这个数组上还添加了几个属性:
index
:开始匹配的下标(没有开启全局匹配时默认是0)input
:完整的字符串groups
:具名组匹配时的各个分组
const str = '2021-10-11a';
const reg = /(\d{4})-(\d{2})-(\d{2})/;
const res = reg.exec(str);
console.log(Array.isArray(res)); // true
console.log(res);
// ['2021-10-11', '2021', '10', '11', index: 0, input: '2021-10-11', groups: undefined];
1
2
3
4
5
6
2
3
4
5
6
# 贪婪匹配
默认情况下,会尽量匹配多的字符,称为贪婪匹配
const str = '123456789'
const reg1 = /(\d{1,3})(\d{1,3})/g
console.log(reg1.exec(str)) // [ '123456', '123', '456', index: 0, input: '123456789', groups: undefined]
1
2
3
2
3
在匹配数量后添加?
,可采用惰性匹配模式,匹配尽量少的字符
const reg2 = /(\d{1,3}?)(\d{1,3}?)/g
console.log(reg2.exec(str)) // [ '12', '1', '2', index: 0, input: '123456789', groups: undefined]
1
2
2
# 断言匹配
某一部分是否匹配成功取决于前后元素的情况,属于上下文有关的匹配
x(?=y)
:只有x之后是y才匹配(?<=y)x
:只有x之前是y才匹配x(?!y)
:只有x之后不是y才匹配(?<!y)x
:只有x之前不是y才匹配
# 分组匹配
用括号()
将内容括起来,可以将正则表达式分为若干个部分,分组的内容会反应在exec
方法返回的数组中
同时,每个分组可以进行命名,称为具名组匹配
const str = '2021-10-10asd';
const reg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
console.log(reg.exec(str).groups) // { year: '2021', month: '10', day: '10' }
1
2
3
2
3