easy-vibe 正则表达式实战指南:从字符类到前瞻断言,用一行模式解决 80% 的文本检索与校验问题
【免费下载链接】easy-vibe💻 vibe coding 101|The first course for AI-native product builders.项目地址: https://gitcode.com/GitHub_Trending/ea/easy-vibe
导读:正则表达式看似天书,本质只是“描述文本模式的小型语言”。本篇以 easy-vibe 附录知识库《正则表达式基础》为骨架,完整覆盖字符类、量词、位置锚点与分组三大积木块,详解邮箱、手机号、密码强度等高频校验模式,并对照 Python
re与 JavaScript 正则 API 给出可直接运行的代码示例;最后结合本仓库脚本(如 book-shared.mjs、generate-sitemap.mjs)中的真实正则用法,验证“贪婪与懒惰匹配”“分组捕获”“正则替换”等核心概念在生产代码中的实际形态。读完本文,你将具备用几行正则解决大多数文本查找、提取、替换与校验问题的实战能力。
1. 为什么需要正则表达式
先设想几个真实场景:
- 从一份冗长的日志文件中提取所有 IP 地址;
- 校验用户输入的邮箱格式是否合法;
- 把文本中的日期从
2024/01/15统一替换为2024-01-15; - 从网页源码中提取所有链接。
如果用普通的字符串查找方法,你需要编写大量if-else分支逻辑,逐字符或逐子串判断;而用正则表达式,一个模式即可完成。这也是 easy-vibe 将正则基础放在“开发工具”附录(docs/es-es/appendix/2-development-tools/)中的原因:它是贯穿前端校验、后端数据清洗、日志分析、代码重构全流程的通用技能。
一句话理解:正则表达式 = 用特殊符号描述“你想找什么样的文本”。
\d表示数字,+表示一个或多个,所以\d+就是“一个或多个数字”。
2. 核心概念:像搭积木一样组合模式
正则的本质是用三类积木块组合出你想要的匹配模式。理解这三类积木,就等于掌握了正则 80% 的语法骨架。
2.1 积木块一:字符类(匹配什么字符)
字符类决定“匹配哪些字符”,是正则最基础的单元:
| 语法 | 含义 | 示例 |
|---|---|---|
. | 任意一个字符 | a.c→ abc、a1c、a c |
\d | 数字 [0-9] | \d\d→ 42、99 |
\w | 字母 / 数字 / 下划线 | \w+→ hello、user_1 |
\s | 空白字符 | 匹配空格、制表符 |
[abc] | 集合中的任意一个 | [aeiou]→ 元音字母 |
[^abc] | 不在集合中的任意字符 | [^0-9]→ 非数字字符 |
从 easy-vibe 仓库的构建脚本中可以找到这三类最常用字符类的真实用法。例如 book-shared.mjs 用^\d+\.\d+\.\d+来识别语义化版本号:
const clean = (value) => String(value || '').trim().replace(/^v/, '') if (env && /^\d+\.\d+\.\d+/.test(env)) return env if (/^\d+\.\d+\.\d+/.test(ghRef)) return ghRef if (/^\d+\.\d+\.\d+/.test(tag)) return tag这里\d+(一个或多个数字)与\.(转义后的点号)组合,精确锁定了x.y.z三段式版本号格式;/^v/则用字符类之外的普通字符字面量剥离版本号开头的v前缀。这说明即使是在构建系统这类基础设施代码中,\d、\w、\s也是最常被引用的字符类。
2.2 积木块二:量词(匹配多少次)
量词决定“前面那个单元出现几次”:
| 语法 | 含义 | 示例 |
|---|---|---|
* | 0 次或多次 | ab*→ a、ab、abbb |
+ | 1 次或多次 | ab+→ ab、abbb(不匹配 a) |
? | 0 次或 1 次 | colou?r→ color、colour |
{3} | 恰好 3 次 | \d{3}→ 123 |
{2,4} | 2 到 4 次 | \d{2,4}→ 12、1234 |
量词是正则“一行模式解决问题”的威力来源:{n}精确计数、*/+/?表达“可有可无”或“重复多次”的模糊需求。例如判断“这位用户是否满足最低密码长度”时,{8,}就是“至少 8 位”的直接翻译(见 3.3 节)。
2.3 积木块三:位置与分组(在哪里匹配、怎么组织)
位置锚点与分组决定匹配发生的位置以及结果如何被组织:
| 语法 | 含义 | 示例 |
|---|---|---|
^ | 行首 | ^Hello→ 以 Hello 开头的行 |
$ | 行尾 | end$→ 以 end 结尾的行 |
\b | 单词边界 | \bcat\b→ cat(不匹配 catch) |
(...) | 捕获组 | (\d+)-(\d+)→ 分别捕获两部分 |
a\|b | 或 | cat\|dog→ cat 或 dog |
捕获组在“提取”场景中价值极高:不仅告诉你“匹配成功了”,还告诉你“匹配到的东西里每一部分各是什么”。easy-vibe 的发布脚本 book-shared.mjs 就用分组从 Git 仓库地址中提取作者与仓库名:
const sshMatch = repository.match(/github\.com:(.+?)\/(.+?)(\.git)?$/)(.+?)是非贪婪捕获组(详见第 5 节),(\.git)?$是“可选的 .git 后缀 + 行尾锚点”,三组配合即可从 SSH 地址中分离出组织名、仓库名。\b单词边界则常用于“精确匹配整个词”而避免误伤子串(如cat匹配到catch内部)。
3. 实战:三组高频校验模式
以下三组模式来自原文档第 3 节,是开发中最常被复用的现成模式,建议直接收藏。
3.1 邮箱校验
[\w.+-]+@[\w-]+\.[\w.]+逐段拆解:
[\w.+-]+— 用户名部分(字母、数字、点、加号、连字符),一个或多个;@— 字面量 @ 符号;[\w-]+— 域名部分;\.— 转义后的点号;[\w.]+— 顶级域名部分。
3.2 手机号校验(中国大陆)
1[3-9]\d{9}逐段拆解:
1— 以 1 开头;[3-9]— 第二位数字为 3-9(覆盖当前主流号段);\d{9}— 后接 9 位数字,共 11 位。
3.3 密码强度校验
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$逐段拆解:
(?=.*[a-z])— 至少包含一个小写字母(前瞻断言,只“看”不“消费”字符);(?=.*[A-Z])— 至少包含一个大写字母;(?=.*\d)— 至少包含一个数字;.{8,}— 总长度至少 8 个字符;^与$锚定整个字符串,确保断言作用于全文而非局部。
使用要点:正则表达式默认是“局部匹配”——只要文本中的某一段能匹配成功就算命中。因此在做格式校验时必须显式加上^...$(JS 中还可用match的全局匹配或 Python 的fullmatch)来锁定整段字符串;否则上面的密码模式可能放过“含 8 位以上子串但不满足整体要求”的输入。
4. 在代码中使用正则表达式
原文档给出 JavaScript 与 Python 两种主流语言的对照用法,下面完整继承并补充说明。
4.1 JavaScript
const text = '联系方式:13812345678 或 15099887766' const regex = /1[3-9]\d{9}/g const phones = text.match(regex) // ['13812345678', '15099887766'] // 替换:隐藏手机号中间四位 text.replace(/\d{4}(?=\d{4}$)/, '****') // 校验 /^[\w.+-]+@[\w-]+\.[\w.]+$/.test('user@example.com') // true三个要点:
g标志(global):不加g时match只返回第一个匹配;加g后返回全部匹配数组;replace与前瞻(?=...)组合:\d{4}(?=\d{4}$)匹配“后面紧跟末尾 4 位数字的那 4 位数字”,配合 replace 即实现“隐藏中间四位”而不影响最后四位,这正是前瞻断言“只看不消费”的典型生产用途;.test():返回布尔值,适合放在表单校验分支中。
4.2 Python
import re text = '价格是 99 元,优惠 20 元' numbers = re.findall(r'\d+', text) # ['99', '20'] # 替换 re.sub(r'\d+', 'X', text) # '价格是 X 元,优惠 X 元' # 分组捕获 match = re.search(r'(\d+)-(\d+)', '2024-01-15') match.group(1) # '2024' match.group(2) # '01'三个要点:
- 原始字符串
r'...':推荐始终使用原始字符串书写正则,避免\d、\s等被 Python 字符串转义规则二次处理; re.findall返回所有非重叠匹配的列表,是“提取全部”的主力 API;match.group(n)按括号顺序访问捕获组,是“解析结构化文本”的入口。
5. 贪婪 vs. 懒惰:一个关键差异
看下面的经典场景:
文本:<b>hello</b> and <b>world</b>| 模式 | 匹配结果 | 说明 |
|---|---|---|
<b>.*</b> | <b>hello</b> and <b>world</b> | 贪婪:尽可能多匹配 |
<b>.*?</b> | <b>hello</b> | 懒惰:尽可能少匹配 |
默认是贪婪模式——量词会尽量“吃”更多字符,直到无法继续扩展;在量词后追加?即切换为懒惰模式,匹配到第一个满足条件的位置就停止。绝大多数需要“逐条提取”的场景(如提取所有 HTML 标签、所有链接)都应当使用懒惰模式。
仓库脚本中同样随处可见这一原则的实战应用。例如 book-shared.mjs 解析 Vue 组件首标签时使用:
const openMatch = first.match(/^\s*<([A-Z][A-Za-z0-9_:-]*)\b/) const closeMatch = first.match(/^\s*<\/...>/)而 HTML 代码块剥离(book-shared.mjs)采用[\s\S]*?这种“任意字符(含换行)懒惰匹配”来剔除<script>、<style>、<template>块:
.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, '\n') .replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, '\n')提示:
.默认不匹配换行符,所以跨行匹配常写成[\s\S]*?(空白 + 非空白 = 一切字符)或[\s\S]*。
再如 generate-sitemap.mjs 用replace(/\.md$/, '')把 Markdown 路径转换为 URL 路径——\.md转义点号 +$行尾锚点,精确剥离扩展名;随后(generate-sitemap.mjs)用一串.replace(/&/g, '&')等调用对 URL 做 XML 实体转义。这些例子说明:文本清洗、路径转换、HTML/XML 转义正是正则替换最主力的三大生产场景。
6. 小结与速查
- 正则 = 描述文本模式的小型语言,用于查找、匹配与替换;
- 三类积木块:字符类(匹配什么)+ 量词(匹配多少次)+ 位置/分组(在哪里匹配、如何组织结果);
\d\w\s是三大最高频字符类,覆盖数字、单词字符与空白;- 不必从零编写:邮箱、手机号、密码等常见场景已有成熟模式可直接复用;
- 贪婪 vs. 懒惰:默认为贪婪(匹配更多),量词后加
?变为懒惰(匹配更少)。
继续学习:
- 环境变量与 PATH 入门 — 理解系统配置
- SSH 与密钥认证入门 — 安全连接远程服务器
- 更多开发工具基础可回到 开发工具附录 总览
【免费下载链接】easy-vibe💻 vibe coding 101|The first course for AI-native product builders.项目地址: https://gitcode.com/GitHub_Trending/ea/easy-vibe
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考