别再说正则难学了,看完这篇你就懂了
前言
前几天在刷面试题的时候,遇到一个拼多多的笔试题:如何验证用户输入的手机号是否正确?
要求很简单:
- 11位数字
- 以1开头
- 第二位不能是0、1、2
- 后9位任意数字
这不就是正则表达式的经典场景吗?今天我们就从这个题目出发,把正则表达式彻底讲明白。
一、手机号校验:正则入门第一课
需求分析
永远不要相信用户的输入------这是前端开发的第一原则。用户可能输入空字符串、特殊字符、或者长度不对的号码,我们需要在前端做一层校验。
咱们的需求翻译成正则语言:
- 11位数字 →
{11}表示匹配11次 - 以1开头 →
^1表示字符串开头必须是1 - 第二位不能是0/1/2 →
[3-9]表示只匹配3-9 - 后9位任意数字 →
\d{9}表示9个数字
组合起来:
javascript
ini
let str = '13888888888';
let reg = /^1[3-9]\d{9}$/;
console.log(reg.test(str)); // true
正则符号速查表
| 符号 | 含义 | 示例 |
|---|---|---|
/ / |
正则字面量 | /abc/ |
^ |
匹配开头 | ^1 |
$ |
匹配结尾 | \d$ |
[] |
字符范围 | [3-9] |
{} |
匹配次数 | {9} |
\d |
数字 | 等价于 [0-9] |
+ |
一次或多次 | \d+ |
g |
全局匹配 | /\d+/g |
() |
分组捕获 | /(\w+)/ |
二、match:提取你想要的内容
假设我们有一个字符串 '价格是100元成本是80元',想把所有数字提取出来:
javascript
ini
const str = '价格是100元成本是80元';
const reg = /\d+/g;
const result = str.match(reg);
console.log(result); // ['100', '80']
注意这里的 g 修饰符很关键!没有它,match 只会返回第一个匹配的结果。
三、replace + 分组捕获:最实用的组合
来看一个经典场景:把 'hello-world' 转成 'helloWorld'(驼峰命名)。
javascript
javascript
const str = 'hello-world';
const reg = /-(\w)/; // (\w) 是一个分组,匹配连字符后面的字母
console.log(str.match(reg));
// ['-w', 'w', index: 5, input: 'hello-world', groups: undefined]
// ↑ ↑
// 完整 分组1
const res = str.replace(reg, (_, c) => {
return c.toUpperCase();
});
console.log(res); // 'helloWorld'
回调函数参数说明
- 第1个参数:完整匹配
-w - 第2个参数:第一个分组捕获的内容
w - 返回值会替换掉完整匹配的内容
四、exec:逐条提取分组信息
exec 比 match 更强大,它可以逐条获取匹配信息,并且每次调用会移动指针:
javascript
javascript
const reg = /(\d+)/g;
const str = '年龄18,身高175';
let result;
while ((result = reg.exec(str)) !== null) {
console.log(`找到 ${result[0]},分组内容 ${result[1]}`);
}
// 找到 18,分组内容 18
// 找到 175,分组内容 175
五、实战:手写一个简易模板引擎
有了上面的基础,我们来写一个简单的模板引擎:
javascript
javascript
let template = '我是{{name}},年龄{{age}},性别{{sex}}';
let person = {
name: '赖庆庆',
age: 17,
sex: '男'
};
function render(template, data) {
const reg = /{{(\w+)}}/g; // 注意这里加了 g,全局匹配
return template.replace(reg, (match, key) => {
return data[key] || '';
});
}
console.log(render(template, person));
// 输出:我是赖庆庆,年龄17,性别男
原理拆解
/{{(\w+)}}/g匹配所有{{xxx}},并用(\w+)捕获中间的变量名replace的回调函数接收match(完整匹配如{{name}})和key(捕获的name)- 从
data对象中取出对应的值进行替换
六、扩展:如何判断JS数据类型?
既然聊到了 Object.prototype.toString.call(),顺便复习一下JS数据类型判断:
javascript
javascript
// 基本类型
typeof 'hello' // 'string'
typeof 123 // 'number'
typeof true // 'boolean'
typeof undefined // 'undefined'
typeof null // 'object' ⚠️ 这是JS的bug
// 引用类型
const reg = /abc/;
Object.prototype.toString.call(reg); // '[object RegExp]'
Object.prototype.toString.call([]); // '[object Array]'
Object.prototype.toString.call({}); // '[object Object]'
总结
| 方法 | 用途 | 返回值 |
|---|---|---|
test() |
判断是否匹配 | boolean |
match() |
提取匹配内容 | 数组 |
replace() |
替换 + 分组捕获 | 新字符串 |
exec() |
逐条提取分组 | 数组(带index) |
正则表达式就像一门微型编程语言,学会它,字符串处理的能力会上一个台阶。希望这篇文章对你有帮助!
如果你觉得有用,欢迎点赞收藏~