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

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

前言

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

要求很简单:

  • 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)

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


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

相关推荐
To_OC1 小时前
从一次栈溢出报错说起,我把递归彻底扒明白了
javascript·算法·程序员
kyriewen3 小时前
面试官问你:“AI 能写 80% 的代码了,公司为什么还需要你?”
前端·javascript·面试
Goodbye6 小时前
从 Token 到 Embedding:LLM 核心基础深度解析
javascript·人工智能
用户938515635076 小时前
工具调用背后:LLM 如何突破“缸中大脑”,操控真实世界?
javascript·人工智能
Goodbye6 小时前
从函数到智能:LLM Tool Use 深度解析
javascript·人工智能
半个落月6 小时前
大模型到底是怎么“调用工具”的?从一个 Node.js Demo 看懂 Tool Use
javascript·人工智能
烬羽6 小时前
中英文 token 数量差一倍?两段 JS 代码搞懂 LLM 底层是怎么"读"文字的
javascript·程序员·架构
山河木马6 小时前
矩阵专题1-怎么创建模型矩阵(uModelMatrix)
javascript·webgl·计算机图形学
前端开发爱好者11 小时前
支持 110 种文件预览!兼容 Vue、React、Svelte!
前端·javascript·vue.js
大家的林语冰12 小时前
👍 尤大重学 Webpack,Vite 8.1 再进化,打包模式复活!
前端·javascript·vite