前端学习正则表达式
Juns正则表达式
一直以来都避免接触正则 😠,因为感觉都是啥,看不懂,好难看,不想学 🥺。不过还是有必要了解学习一下的,至少要能看懂,知道在什么时候使用它,当然具体的表达式可以直接百度或者问 GPT,看得懂意思就好。
正则表达式是匹配模式,要么匹配字符,要么匹配位置。
搞懂位置能干啥?
- 数字的千分位分割法
123456789 -> 123,456,789 
 
- 手机号 3-4-4 分割
12345678901 -> 123-4567-8901 
 
- 密码合法性校验
密码长度是 6-12 位,由数字、小写字符和大写字母组成,但必须至少包括 2 种字符 
 
上面也都是很常见的需求,正则可以很方便的解决他们
什么是位置
位置可以理解为相邻字符之间的位置,可以类比为空字符串,在字符的首尾、间隙用空字符连接
| 'he' === '' + 'h' + '' + 'e' + ''
 | 
有哪些位置
正则中常用来表示位置的符号主要有:
^、$、\b、\B、?=p、(?!p)、(?<=p)、(?<!p)
^
匹配行的开头
如果要在 hello 开头赛一个笑脸 😊,就可以这么写
| let str = 'hello'console.log(str.replace(/^/, '😊'))
 
 
 | 
$
匹配行的结尾
同理在 hello 的末尾赛一个笑脸 😊
| console.log('hello'.replace(/$/, '😊'))
 | 
\b
单词的边界
匹配一个单词边界,即字和空格之间的位置
比如想把xxx_1.mp4变成❤️xxx_1❤️.❤️mp4❤️,就可以这么写
| let str = 'xxx_1.mp4'console.log(str.replace(/\b/, '❤️'))
 
 console.log(str.replace(/\b/g, '❤️'))
 
 
 | 
\B
非单词的边界,就是和\b 相反
直接看例子吧:
| let str = 'xxx_1.mp4'console.log(str.replace(/\B/, '❤️'))
 
 console.log(str.replace(/\B/g, '❤️'))
 
 
 | 
(?=p)
p 为正向先行断言,表示 p 前面的位置
比如想把xxx_1.mp4变成❤️xxx_1.mp4,就可以这么写
| let str = 'xxx_1.mp4'console.log(str.replace(/(?=xxx)/, '❤️'))
 
 
 | 
(?!p)
p 为负向先行断言,表示不在 p 前面的位置
| let str = 'xxx_1.mp4'console.log(str.replace(/(?!xxx)/, '❤️'))
 
 console.log(str.replace(/(?!xxx)/g, '❤️'))
 
 
 | 
(?<=p)
p 为正向后行断言,表示 p 后面的位置
| let str = 'xxx_1.mp4'console.log(str.replace(/(?<=xxx)/, '❤️'))
 
 
 | 
(?<!p)
p 为负向后行断言,表示不在 p 后面的位置
| let str = 'xxx_1.mp4'console.log(str.replace(/(?<!xxx)/, '❤️'))
 
 console.log(str.replace(/(?<!xxx)/g, '❤️'))
 
 
 | 
尝试做题
数字的千分位分割法
将 123456789 转化为 123,456,789
从后往前,每 3 个数字前面加一个逗号,这很符合(?=p)
- 先吧最后一个逗号弄出来
| let price = '123456789'let priceReg = /(?=\d{3}$)/
 console.log(price.replace(priceReg, ','))
 
 
 | 
- 弄出所有的逗号
| let price = '123456789'let priceReg = /(?=(\d{3})+$)/g
 
 console.log(price.replace(priceReg, ','))
 
 
 | 
- 去掉第一个逗号
| let price = '123456789'let priceReg = /(?!^)(?=(\d{3})+$)/g
 
 console.log(price.replace(priceReg, ','))
 
 
 | 
手机号 3-4-4 分割
12345678901 -> 123-4567-8901
| let phone = '12345678901'let phoneReg = /(?=(\d{4})+$)/g
 console.log(phone.replace(phoneReg, '-'))
 
 
 | 
手机号 3-4-4 分割拓展
要求这样的形式
| 123 => 1231234 => 123-4
 12345 => 123-45
 123456 => 123-456
 1234567 => 123-4567
 12345678 => 123-4567-8
 123456789 => 123-4567-89
 12345678911 => 123-4567-8911
 
 | 
这个就是和从前往后
- 先弄第一个 -
| const formatPhone = phone => String(phone).replace(/(?<=\d{3})\d+/, '-')console.log(formatPhone(123))
 console.log(formatPhone(1234))
 
 | 
- 第二个
| const formatPhone = phone =>String(phone)
 .slice(0, 11)
 .replace(/(?<=\d{3})\d+/, str => `-${str}`)
 .replace(/(?<=[\d-]{8})\d{1,4}/, str => `-${str}`)
 
 
 console.log(formatPhone(123))
 console.log(formatPhone(1234))
 console.log(formatPhone(12345))
 console.log(formatPhone(123456))
 console.log(formatPhone(1234567))
 console.log(formatPhone(12345678))
 console.log(formatPhone(123456789))
 console.log(formatPhone(12345678911))
 
 | 
校验密码合法性
密码长度是 6-12 位,由数字、小写字符和大写字母组成,但必须至少包括 2 种字符
- 6-12 位
- 数字、小写、大写
- 至少 2 种
先写 12 俩条件
| let reg = /^[a-za-Z\d]{6-12}$/
 | 
条件 3
| let reg = /^(?![a-z]+$)(?![A-Z]+$)(?!\d+$)[a-zA-Z\d]{6,12}$/console.log(reg.test('123456'))
 console.log(reg.test('aaaaaa'))
 console.log(reg.test('AAAAAAA'))
 console.log(reg.test('1a1a1a'))
 console.log(reg.test('1A1A1A'))
 console.log(reg.test('aAaAaA'))
 console.log(reg.test('1aA1aA1aA'))
 
 | 
字符串匹配
俩种模糊匹配
横向
通过+、*、?、{m,n},可实现横向匹配
| let reg = /ab{2,5}c/glet str = 'abc abbc abbbc abbbbc abbbbbc abbbbbbc'
 console.log(str.match(reg))
 
 
 | 
纵向
通过[],可实现纵向匹配
| let reg = /a[123]b/glet str = 'a0b a1b a2b a3b a4b'
 console.log(str.match(reg))
 
 
 | 
字符组
虽然叫字符组,不过也有可能只有一个字符
范围表示法
| [123456abcdefABCDEF] => [1-6a-fA-F]
 | 
排除字符组
使用^来排除
| let reg = /[^abc]/glet str = 'a0b23'
 console.log(str.replace(reg, '❤️'))
 
 
 | 
常见简写
量词
量词 简写
| 1. {m,} 2. {m}
 3. {m,n}
 3. ?
 4. +
 5. *
 
 | 
贪婪匹配 惰性匹配
贪婪会尽可等多匹配符合模式的字符
| let regex = /\d{2,5}/g
 let string = '123 1234 12345 123456'
 string.match(regex)
 
 let regex2 = /\d{2,5}?/g
 string.match(regex)
 
 | 
多选分支
| let regex = /good|nice/glet string = 'good idea, nice try.'
 string.match(regex)
 
 | 
题目
- 匹配 id
| let regex1 = /id=".*?"/
 
 let string = '<div id="container" class="main"></div>'
 console.log(string.match(regex1)[0])
 
 let regex2 = /id="[^"]*"/
 console.log(string.match(regex2)[0])
 
 | 
- 匹配 16 进制颜色值
| 
 
 
 
 
 
 
 let regex = /#([a-fA-F\d]{6}|[a-fA-F\d]{3})/g
 let string = '#ffbbad #Fc01DF #FFF #ffE'
 
 console.log(string.match(regex))
 
 
 | 
- 匹配 24 小时制时间
| 
 
 
 
 
 
 
 
 
 
 
 let regex = /^([01]\d|2[0-3]):[0-5]\d$/
 
 console.log(regex.test('23:59'))
 console.log(regex.test('02:07'))
 
 
 let regex = /^(0?\d|1\d|2[0-3]):(0?|[1-5])\d/
 
 console.log(regex.test('23:59'))
 console.log(regex.test('02:07'))
 console.log(regex.test('7:09'))
 
 | 
括号的作用
分组
让量词作用于一个整体
| let reg = /(ab)+/glet string = 'ababa abbb ababab'
 
 console.log(string.match(reg))
 
 
 | 
分支结构
| let reg = /I love (JavaScript|Regular Expression)/
 console.log(reg.test('I love JavaScript'))
 
 console.log(reg.test('I love Regular Expression'))
 
 
 | 
总结
感觉还是不好理解,不过能看懂一些符号的含义了 ☹️
参考链接