从手机号校验到模板引擎:正则表达式的实战之旅

别再说正则难学了,看完这篇你就懂了

前言

前几天在刷面试题的时候,遇到一个拼多多的笔试题:如何验证用户输入的手机号是否正确?

要求很简单:

  • 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:逐条提取分组信息

execmatch 更强大,它可以逐条获取匹配信息,并且每次调用会移动指针:

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,性别男

原理拆解

  1. /{{(\w+)}}/g 匹配所有 {{xxx}},并用 (\w+) 捕获中间的变量名
  2. replace 的回调函数接收 match(完整匹配如 {{name}})和 key(捕获的 name
  3. 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)

正则表达式就像一门微型编程语言,学会它,字符串处理的能力会上一个台阶。希望这篇文章对你有帮助!


如果你觉得有用,欢迎点赞收藏~

相关推荐
Hello馒头儿1 小时前
vue3+uniapp经典hook方式实现一个更多加载的列表组件
前端·javascript·vue.js
用户938515635071 小时前
前端必会:从 Fetch 到 DeepSeek,一篇搞懂 HTTP 请求的方方面面
javascript·架构
半个烧饼不加肉1 小时前
JS 底层探究--执行上下文
开发语言·前端·javascript
山河木马2 小时前
无框架-原生webGL渲染-底层入门-1
前端·javascript·webgl
小李云雾2 小时前
深入浅出 Vue 3 核心知识点:从基础到实战
前端·javascript·vue.js·程序人生
Cobyte2 小时前
16.响应式系统比对:链表如何实现 computed 的高效更新
前端·javascript·vue.js
坏柠2 小时前
从一个设备控制面板开始,系统学习 LVGL 界面开发
android·javascript·学习
陈_杨2 小时前
鸿蒙APP开发-带你走进黑胶阁的唱片收藏怎么管理
前端·javascript
一天 24h2 小时前
Pinia 新手完全指南:从入门到精通的实战教程
前端·javascript·vue.js·pycharm·前端框架