学习正则表达式后🤔直接开始面试😱

374 阅读8分钟

前言

前期 , 看到团内多个学长冲击大厂的面试题有关正则表达式 , 趁着春节下午休闲 , 搞一搞 ~

📅 安排如下:

  • 先进行基础学习 , 学习正则的规律
  • 之后开始写题目 , 巩固强化训练
  • 最后直接面试🤡
    • 腾讯校招笔试题
    • 百度面试题

基础学习

正则表达式(Regular Expression,简称 Regex)就像“文字查找和替换的高级工具”,通过简单的符号规则,快速匹配、查找、替换复杂的文本。以下是小白也能快速记住的核心规则,用 符号 + 例子 + 口诀 帮你理解!

🧠 正则表达式(Regular Expression,简称 Regex)就像“文字查找和替换的高级工具”,通过简单的符号规则,快速匹配、查找、替换复杂的文本。以下是小白也能快速记住的核心规则,用 符号 + 例子 + 口诀 帮你理解!

🔍 配合例子快速过一遍正则表达式,我要匹配一个字符串,需要搞懂:

  • 匹配字符串中的谁?
  • 匹配这个“谁”或这些“谁”多少次?
  • 在字符串中哪里匹配?

之后则是一些特殊处理:

  • 分组与逻辑
  • 转义字符
  • 全局匹配否?

一、基础符号:匹配“谁”

符号作用例子口诀
abc匹配具体字符 abc"a" → 匹配 a字面匹配
.匹配任意一个字符"a.c"abc/a1c点代表任意
\d匹配数字(0-9)\d0/5d 是 digit
\w匹配字母、数字、下划线\wa/3/_w 是 word字符
\s匹配空白符(空格、换行等)\s → 空格s 是 space
[abc]匹配括号中任意一个字符[ae]a/e中括号里选一个
[^abc]匹配不在括号中的字符[^ae]b/3^ 是取反
[a-z]匹配范围内的字符[0-9] → 数字连字符表范围

二、量词:匹配“多少次”

符号作用例子口诀
*匹配0次或多次a*""/a/aaaa星号是零或多
+匹配1次或多次a+a/aaa(不能空)加号至少一次
?匹配0次或1次a?""/a问号可有可无
{n}匹配恰好n次a{3}aaa花括号精确次数
{n,}匹配至少n次a{2,}aa/aaaa逗号表下限
{n,m}匹配n到m次a{2,4}aa/aaaa逗号分隔范围

三、位置:匹配“在哪里”

符号作用例子口诀
^匹配字符串开头^a → 开头的 a^ 是开头
$匹配字符串结尾a$ → 结尾的 a$ 是结尾
\b匹配单词边界\bcat\b → 匹配单词 catb 是边界

四、分组与逻辑

符号作用例子口诀
(abc)分组,后续可引用(ab)+abab括号分组
``逻辑或`a

五、转义符:匹配特殊符号

符号作用例子口诀
\转义符号本身(如 .*\. → 匹配 .反斜杠转义

六、标志(Flags):全局匹配模式

标志作用例子口诀
g全局匹配(所有结果)/a/g → 所有 ag 是 global
i忽略大小写/a/iA/ai 是 ignore case

七、快速记忆口诀🚀🚀🚀

  1. . 任意,\d 数字,\w 字,\s 空。
  2. [] 选一个,^ 开头 $ 结尾。
  3. * 零或多,+ 一或多,? 零或一。
  4. {} 次数定,| 是或,() 分组用。
  5. \ 要转义,g 全局 i 不区分。

八、实战例子

  1. 匹配手机号:/^1[3-9]\d{9}$/
    • 1 开头,第二位是 3-9,后面接9位数字。
  2. 删除所有空格:s.replace(/\s/g, '')
  3. 匹配邮箱:/\w+@\w+\.[a-z]+/i

九 实际开发手段

  1. 多用在线工具(如 Regex101),实时测试表达式。
  2. 从简单需求开始(如查找数字),逐步增加复杂度。
  3. 记住常见规则,其他查文档即可!

正则表达式看似复杂,但掌握核心符号后,就能轻松应对大部分需求! 🚀

实战

以下是关于正则表达式的常见面试题,涵盖基础、进阶和实战应用,巩固知识并应对面试!

一、基础题

  1. 什么是正则表达式?它的作用是什么?
    • 提示:正则表达式是一种用于匹配、查找和替换文本的工具,常用于验证输入、提取数据等。
  2. 如何匹配一个数字?
    • 答案:\d[0-9]
  3. 如何匹配一个非数字字符?
    • 答案:\D[^0-9]
  4. 如何匹配一个单词字符(字母、数字、下划线)?
    • 答案:\w
  5. 如何匹配空白字符(空格、换行、制表符等)?
    • 答案:\s
  6. 如何匹配任意字符?
    • 答案:.
  7. 如何匹配字符串的开头和结尾?
    • 答案:^ 匹配开头,$ 匹配结尾。

二、进阶题

  1. 如何匹配一个邮箱地址?
    • 答案:/\w+@\w+\.[a-z]+/i(简单版)。
  2. 如何匹配一个手机号(中国大陆)?
    • 答案:/^1[3-9]\d{9}$/
  3. 如何匹配一个 URL?
    • 答案:/https?:\/\/[\w\-\.]+(\/[\w\-\.]*)*/i
  4. 如何匹配一个 HTML 标签?
    • 答案:/<[^>]+>/
  5. 如何匹配一个日期(格式:YYYY-MM-DD)?
    • 答案:/\d{4}-\d{2}-\d{2}/
  6. 如何匹配一个 IP 地址?
    • 答案:/(\d{1,3}\.){3}\d{1,3}/
  7. 如何匹配一个十六进制颜色值(如 #FFFFFF)?
    • 答案:/#[0-9a-fA-F]{6}/

三、实战题

  1. 写一个正则表达式,删除字符串中的所有空格。
    • 答案:s.replace(/\s/g, '')
  2. 写一个正则表达式,提取字符串中的所有数字。
    • 答案:s.match(/\d+/g)
  3. 写一个正则表达式,验证密码强度(至少8位,包含大小写字母和数字)。
    • 答案:/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}$/
  4. 写一个正则表达式,匹配所有以 ing 结尾的单词。
    • 答案:/\b\w+ing\b/g
  5. 写一个正则表达式,匹配所有以 httphttps 开头的 URL。
    • 答案:/^https?:\/\/\S+/
  6. 写一个正则表达式,匹配所有中文汉字。
    • 答案:/[\u4e00-\u9fa5]/
  7. 写一个正则表达式,匹配所有 HTML 注释(<!-- 注释 -->)。
    • 答案:/<!--[\s\S]*?-->/

四、综合题

  1. 如何用正则表达式实现一个简单的模板引擎(如替换 {{name}} 为实际值)?
    • 提示:使用 replace 和分组捕获。
  2. 如何用正则表达式验证一个字符串是否为合法的 JSON 格式?
    • 提示:JSON 格式复杂,正则表达式只能做简单验证。
  3. 如何用正则表达式提取字符串中的所有 URL?
    • 提示:结合 match 和 URL 正则表达式。
  4. 如何用正则表达式实现一个简单的词法分析器?
    • 提示:结合分组和量词,匹配不同 token。
1. 如何用正则表达式实现一个简单的模板引擎(如替换 {{name}} 为实际值)?

思路:
使用 String.prototype.replace 方法结合正则表达式的分组捕获功能来实现模板字符串的替换。

示例代码:

function renderTemplate(template, data) {
  return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
    return data[key] !== undefined ? data[key] : match;
  });
}

const template = "Hello, {{name}}! Welcome to {{place}}.";
const data = { name: "Alice", place: "Wonderland" };
console.log(renderTemplate(template, data)); // 输出: Hello, Alice! Welcome to Wonderland.
2. 如何用正则表达式验证一个字符串是否为合法的 JSON 格式?

注意:
JSON 格式非常复杂,使用正则表达式进行完整的 JSON 验证是不现实的。正则表达式更适合用于简单的模式匹配,而不是复杂的结构化数据验证。建议使用 JSON.parse 方法来验证 JSON 字符串。

示例代码:

function isValidJSON(str) {
  try {
    JSON.parse(str);
    return true;
  } catch (e) {
    return false;
  }
}

console.log(isValidJSON('{"name":"Alice","age":30}')); // 输出: true
console.log(isValidJSON('{"name":"Alice","age":30'));  // 输出: false
3. 如何用正则表达式提取字符串中的所有 URL?

思路:
使用 String.prototype.match 方法结合一个简单的 URL 正则表达式来提取字符串中的所有 URL。

示例代码:

function extractURLs(text) {
  const urlPattern = /(https?:\/\/[^\s]+)/g;
  return text.match(urlPattern) || [];
}

const text = "Check out these links: https://www.example.com and http://www.test.com.";
console.log(extractURLs(text)); // 输出: ["https://www.example.com", "http://www.test.com"]
4. 如何用正则表达式实现一个简单的词法分析器?

思路:
使用正则表达式的分组和量词来匹配不同的 token。这里以一个简单的算术表达式为例,提取数字、运算符和括号。

示例代码:

function tokenize(expression) {
  const tokenPattern = /(\d+|[+\-*/()])/g;
  return expression.match(tokenPattern) || [];
}

const expression = "3 + 5 * (2 - 8)";
console.log(tokenize(expression)); // 输出: ["3", "+", "5", "*", "(", "2", "-", "8", ")"]

五、面试

腾讯校招笔试
题目

var s = 'abc345efgabcab'

写出三条JS 语句实现一下三个功能(使用正则)

1)去掉字符串中的a、b、c 字符,形成结果:'345efg'

2)将字符串中的数字用中括号括起来,形成结果:'abc[345]efgabcab'

3)将字符串中的每个数字的值分别乘以 2,形成结果:'abc6810efgabcab'

解题

这道题目 ,理解上面基础知识 , 即可写出

var s = 'abc345efgabcab'


// 1) 

var reg = /[abc]/g

var res = s.replace(reg,'')

console.log(res)


// 2)

var reg = /\d+/g

var res = s.replace(reg,function(item){
    return '[' + item + ']'
})

console.log(res) 


// 3)


var reg = /\d+/g

var res = s.replace(reg,function(item){
    return item * 2
})


console.log(res)


百度面试
题目

面试官问:下面这段代码怎么实现页面渲染?

let str = '我是{{name}},年龄{{age}},性别{{sex}}'
let person = {
  name: '张三',
  age: 18,
  sex: '男'
}

请手写一个函数compile , 实现这个效果

模板编译原理

模板编译的核心流程(重点!!!)

  • 模板字符串转 AST:将模板字符串解析为抽象语法树(AST),AST 是一个树形结构,包含模板的语法结构(标签、属性、文本节点等)。
  • 优化 AST:通过静态分析识别静态节点,后续会跳过这些节点的重新渲染。
  • 生成渲染函数:将 AST 转换为渲染函数,渲染函数会生成虚拟 DOM(VNode)。
  • 更新视图:将虚拟 DOM 渲染到页面,实现数据驱动视图更新。

我来用最通俗易懂的方式解释模板编译的流程,就像搭积木一样简单:

🏗️ 第1步:把模板变成结构图(AST)

  • 想象你要组装乐高,首先要看懂说明书。这里我们把HTML模板(比如<div id="app">{{message}}</div>)拆解成一个树形结构图(AST)
  • 就像用不同颜色的积木区分零件:标签是蓝色积木,属性是红色积木,文本是黄色积木
  • 正则表达式就像分类工具(比如用筛子把不同形状的积木分开),帮我们快速识别标签名、属性、文本内容

🌲 举个AST例子:

{
  tag: 'div',
  attrs: [{ id: 'app' }],
  children: [{
    type: 'text',
    content: '{{message}}'
  }]
}

🎯 第2步:给积木做标记(优化AST)

  • 找到永远不会变动的积木(比如纯文字的<div>我是固定标题</div>
  • 给这些"静态积木"贴上荧光贴纸标记
  • 之后更新时就可以跳过这些标记过的积木,提升效率

🛠️ 第3步:生成组装说明书(渲染函数)

  • 把结构图翻译成JS代码,生成类似这样的函数:
function render() {
  return _c('div', { id: 'app' }, _v(message))
}
  • _c是创建元素的方法,_v是创建文本的方法
  • 这个函数执行后会生成虚拟DOM(就像乐高的3D设计图)

🔄 第4步:按图纸更新(视图更新)

  • 当数据变化时(比如message改变),重新生成虚拟DOM
  • 对比新旧设计图,找出需要修改的积木块
  • 只更新变化的部分到真实DOM,就像只替换掉发黄的积木块

🔑 关键记忆点:

  1. 模板 → AST(拆解结构)
  2. 优化AST(找固定零件)
  3. AST → 渲染函数(写说明书)
  4. 虚拟DOM → 真实DOM(按图组装)

整个过程就像:

  1. 把乐高图纸分类整理 📑 →
  2. 标出固定部分 🏷️ →
  3. 写成组装步骤 📝 →
  4. 按步骤拼装/更新积木 🧩

正则表达式在这里就像各种形状的筛子,帮我们快速分离出标签名(圆形筛)、属性(方形筛)、文本(三角形筛),是处理字符串的利器!

模板编译手写

在上面综合题中 , 我们实现了一个

核心代码如下

function renderTemplate(template, data) {
  return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
    return data[key] !== undefined ? data[key] : match;
  });
}

发现主要是写正则表达式 reg = /{{(\w+)}}/g , 关于这个正则 ,经上面学习 , 不难 , 涉及到转移字符和全局匹配

ok ! 直接开搓 !!!

法一

let str = '我是{{name}},年龄{{age}},性别{{sex}}'
let person = {
  name: '张三',
  age: 18,
  sex: '男'
}
const reg = /\{\{(\w+)\}\}/g
function complice(template,data){
  return template.replace(reg,(match,key)=>{
    console.log(match,key)
    return data[key] !==undefined ?  data[key] : match
  })
}


console.log(complice(str,person))

法二

function compile(template, data) {
    let reg = /{{(\w+)}}/;
    if (reg.test(template)) {
      let key = reg.exec(template)[1];
      let value = data[key] || '';
      template = template.replace(reg, value);
      return compile(template, data); // 递归调用
    } else {
      return template;
    }
  }

  console.log(compile(str, person)); // 输出:我是张三,年龄18,性别男