regular expression
- 千分位
str.replace(/(\d)(?=(\d{3})+(\.)?)/g, '$2,');
正则表达式的创建
- 字面量模式 let reg = /\d+/; 缺点是无法拼接变量
- 构造函数模式 let reg = new RegExp('\d+'); 可以拼接变量,可以有第二个参数值为修饰符
// 全局匹配数字为例,下述两个等同
let reg01 = /\d+/g
reg01 = new RegExp('\\d+', 'g')
元字符和修饰符两部分组成
元字符
- 量词元字符:设置出现的次数
符号 | 含义 |
---|---|
* | 零到多次 |
+ | 一到多次 |
? | 零次或一次 |
{ n } | 出现 n 次 |
{ n, } | 出现 n 到多次也就是至少 n 次 |
{ n, m } | 出现 n 到 m 次 |
- 特殊元字符:单个或者组合在一起代表特殊的含义
符号 | 含义 |
---|---|
\ | 转义字符 |
\n | 换行符 |
. | 非 \n |
^ | 以哪一个字符作为开始 |
$ | 以哪一个字符作为结束 |
\d | 0~9之间的一个数字 |
\D | 非 \d |
\w | 数字、字母、_ 下划线中的任意一个字符 |
\W | 非 \w |
\s | 一个空白字符 - 空格、制表、换页符等 |
\t | 制表符 - TAB 键 - 四个空格 |
\b | 匹配一个单词的边界 |
x|y | x 或者 y 中的一个字符 |
[xyz] | x 或者 y 或者 z 中的一个字符 |
[^xy] | 除了 x y 中的任意一个字符 |
[a-z] | a 到 z 这个范围中的任意一个字符比如 [a-z0-9A-Z_] === \w |
[^a-z] | 非 [a-z] |
() | 正则中的分组符号 |
(?:) | 只匹配不捕获 |
(?=) | 正向预查 |
(?!) | 反向预查 |
- 普通元字符:代表的就是本身含义
/protein/: 此正则匹配的就是 "protein"
修饰符
符号 | 含义 |
---|---|
i | ignoreCase 忽略单词大小写匹配 |
m | multiline 可以进行多行匹配 |
g | global 全局匹配 |
易混淆的中括号 [] () ?
[] 的用法
- 里面出现的字符一般都代表其本身的含义 \d 是个例外它还代表数字
// 比如 /^[@+]$/ 代表 @ 或者 + 其中一个
// /^[@+]+\$/ 代表 @ 或者 + 其中一个出现一次或者多次(每次都是独立事件)
let reg03 = /^[@+]$/
console.log(reg03.test('@+')) // false
reg03 = /^[@+]+$/
console.log(reg03.test('@+')) // true
- 中括号中不存在多位数
// 比如 /^[18]$/ 代表 1 或者 8
// /^[(18)]$/ 代表 ( 或者 ) 或者 1 或者 8
// /^[(12-78)]$/ 代表 ( 或者 ) 或者 2 到 7 之前的数字或者 1 或者 8
let reg04 = /^[18]$/
console.log(reg04.test('1')) // true
console.log(reg04.test('8')) // true
console.log(reg04.test('18')) // false
reg04 = /^[12-78]$/
console.log(reg04.test('1')) // true
console.log(reg04.test('6')) // true
console.log(reg04.test('8')) // true
console.log(reg04.test('18')) // false
() 的含义
- 提升优先级
- 分组捕获
- 分组引用,就是通过数 "\数字" 让其代表和对应分组出现一模一样的内容
let str2 = 'book' // 'look' 'hook'这种重复的元素
let reg = /^[a-zA-Z]([a-zA-Z])\1[a-zA-Z]$/
console.log(reg.exec(str2))
? 的含义
- 左边是非量词元字符,代表零次或一次
- 左边是量词元字符,代表取消贪婪性
- (?:) 只匹配不捕获
- (?=) 正向预查
- (?!) 反向预查
常用正则实例
有些具体还是要根据实际业务变通
1. 验证是否为有效数字
/**
* 1. 可能出现 +- 也可能不出现 --- [+-] 或者 (+|-)?
* 2. 一位数位 0-9 都可以,多位数首位不为 0 --- (\d|([1-9]\d+))
* 3. 小数位可能有可能没有,如果有小数点后面必须有数字 --- (\.\d+)?
*/
// let reg06 = /^[+-]?(\d|[1-9]+)(\.\d+)?$/ // 忽略了多位数从第二位开始可能会有 0 的情况
let reg06 = /^[+-]?(\d|([1-9]\d+))(\.\d+)?$/
2. 验证密码
/**
* 数字、字母、下划线
* 6 ~ 16 位
*/
let reg07 = /^\w{6,16}$/
3. 验证真实姓名
/**
* 1. 汉字 /^[\u4E00-\u9FA5]$/
* 2. 长度 2 ~ 10 位
* 3. 可能有译名 ·汉字
*/
let reg08 = /^[\u4E00-\u9FA5]{2,10}(·[\u4e00-\u9FA5]{2,10}){0,2}$/;
4. 验证邮箱
/**
* 1. 开头是数字、字母、下划线,一到多位 --- \w+
* 2. 接下来 -数字、字母、下划线或者 .数字、字母、下划线,它们的整体 0 到多位 --- ((-\w+)|(\.\w+))*
* 1. 2. => 邮箱的名字由 数字、字母、下划线开始和结束,中间可以有不连续的 - 或者 . 出现
* 中间 为 @ 符号
* 3. @ 后面紧跟数字、字母,一到多位 --- [a-zA-Z0-9]+
* 4. 最后匹配域名 一个 . 后面跟一到多个数字或者字母 --- \.[a-zA-Z0-9]+
* 5. 在 4 之前匹配 . 或者 - 后面跟一到多个数字或者字母,它们整体出现 0 到多次 --- ((\.|-)[a-zA-Z0-9]+)*
*/
let reg09 = /^\w+((-\w+)|(\.\w+))*@[a-zA-Z0-9]+((\.|-)[a-zA-Z0-9]+)*\.[a-zA-Z0-9]+$/
5. 身份证号码
/**
* 1. 一共 18 位
* 2. 最后一位可能是 X
* => /^\d{17}[0-9X]$/ /^\d{17}(\d|X)$/
* 3. 规则 - 前六位代表省市县
* 4. 规则 - 中间八位为出生年月日
* 5. 规则 - 最后一位是 X 或者数字
* 6. 规则 - 倒数第二位偶数是女,基数是男
* 7. 规则 - 其余两位根据上述数字计算得出
* => 小括号第二个作用:分组捕获,即不仅匹配整体信息还可以单独捕获小分组的内容
*/
let reg10 = /^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d{1})(\d|X)$/
reg10.exec('130622199708092345') // ["130622199708092345", "130622", "1997", "08", "09", "4", "5", index: 0, input: "130622199708092345", groups: undefined]
// 根据捕获数组可以查询对应省市县,可以知道出生年月日,可以知道性别
// 如果不需要捕获可以用 ?: 只匹配不捕获来处理
let reg10 = /^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d{1})(?:\d|X)$/
reg10.exec('130622199708092345') // ["130622199708092345", "130622", "1997", "08", "09", "4", index: 0, input: "130622199708092345", groups: undefined]
正则的捕获
实现捕获的方法
- RegExp.prototype 的方法 exec 和 test
- String.prototype 的方法 replace\match\splite
exec 方法
- 结果是 null 或者一个数组
let reg11 = /\d+/
let str1 = 'jfla1989protein1997'
let str2 = 'protein'
console.log(reg11.exec(str1)) // [ '1989', index: 4, input: 'jfla1989protein1997', groups: undefined ]
console.log(reg11.exec(str2)) // null
- 懒惰性让它匹捕获到第一个符合条件的内容就会停止
懒惰性的原因:正则有一个 lastIndex 属性,代表下一次匹配的起始位置。exec 之后这个值不会改变,每一次都是从字符串的开始位置 0 查找 - 用全局修饰符 g 来改变 lastIndex 的值,从而打破懒惰性,如下实例形成一个闭环
let reg12 = /\d+/g
let str1 = 'jfla1989protein1997'
console.log(reg12.lastIndex) // 0
console.log(reg12.exec(str1)) // console.log(reg12.lastIndex)
console.log(reg12.lastIndex) // 8
console.log(reg12.exec(str1)) // [ '1997', index: 15, input: 'jfla1989protein1997', groups: undefined ]
console.log(reg12.lastIndex) // 19
console.log(reg12.exec(str1)) // null
console.log(reg12.lastIndex) // 0
console.log(reg12.exec(str1)) // console.log(reg12.lastIndex)
console.log(reg12.lastIndex) // 8
- 字符串的 match 方法可以捕获所有
console.log(str1.match(reg12)) // [ '1989', '1997' ]
test 方法
RegExp.$1 ~ RegExp.$9 获取当前匹配的第一到第九个信息
let str4 = '{2020}年{3}月{6}日'
let reg4 = /\{(\d+)\}/g
console.log(reg4.test(str4)) // true
console.log(RegExp.$1) // 2020
console.log(reg4.test(str4)) // true
console.log(RegExp.$1) // 3
console.log(reg4.test(str4)) // true
console.log(RegExp.$1) // 6
console.log(reg4.test(str4)) // false
console.log(RegExp.$1) // 6
console.log(reg4.test(str4)) // true 同样形成一个闭环
console.log(RegExp.$1) // 2020
replace 字符串中实现替换的方法一般伴随正则使用
- 实例 1 '2020-03-06' === 2020年03月06日
let str13 = '2020-03-06'
let reg13 = /^(\d{4})-(\d{2})-(\d{2})$/
let str131 = str13.replace(reg13, "$1年$2月$3日")
console.log(str131) // 2020年03月06日
实例 1 解析:
- replace 首先拿正则和字符串进行匹配,然后第二个参数接受一个回调函数,匹配几次就会执行几次
- 回调函数接收实参信息 - 为 exec 捕获到的数组里面的值对应实例 1 如下:
let str132 = str13.replace(reg13, (initialstr, $1, $2, $3) => {
console.log(initialstr, $1, $2, $3) // 2020-03-06 2020 03 06
})
- 回调函数的返回值即为 replace 要替换的正则匹配到的内容
let str133 = str13.replace(reg13, (initialstr, ...args) => {
let [$1, $2, $3] = args
$2.length < 2 ? $2 = '0' + $2 : $2
$3.length < 2 ? $3 = '0' + $3 : $3
return $1 + '年' + $2 + '月' + $3 + '日'
})
console.log(str133) // 2020年03月06日
- 实例 2 单词首字母大写
let str14 = 'good good study, day day up!'
let reg14 = /\b([a-zA-Z])([a-zA-Z]*)\b/g
let str141 = str14.replace(reg14, (initialstr, ...args) => {
// 回调函数执行匹配的次数
let [$1, $2] = args
return $1.toUpperCase() + ($2 ? $2 : '')
})
console.log(str141) // Good Good Study, Day Day Up!
正则捕获的贪婪性
默认情况下,捕获的时候是按照当前正则所匹配的最长结果来获取
let str3 = 'jfla1987protein1997'
let reg3 = /\d+/g
console.log(str3.match(reg3)) // [ '1987', '1997' ]
reg3 = /\d/g
console.log(str3.match(reg3)) // [ '1', '9', '8', '7', '1', '9', '9', '7' ]
// 在量词元字符后面加 ? 则取消贪婪模式,按照最短结果来获取
reg3 = /\d+?/g
console.log(str3.match(reg3)) // [ '1', '9', '8', '7', '1', '9', '9', '7' ]
网友评论