正则表达式劝退率极高,但日常真正用得到的语法不超过 8 个符号。这篇不铺理论,直接从「匹配一个手机号」开始,把符号逐个加进去,边写边看效果。
| 符号 | 含义 | 例子 |
|---|---|---|
. | 任意一个字符(换行除外) | a.c 匹配 abc、a1c |
\d | 一个数字 | \d\d 匹配两位数 |
* | 前一项 0 次或多次 | ab* 匹配 a、ab、abbb |
+ | 前一项 1 次或多次 | a+ 匹配 a、aaa |
? | 前一项 0 次或 1 次 | colou?r 匹配 color 和 colour |
{n,m} | 前一项 n 到 m 次 | \d{11} 恰好 11 位数字 |
[ ] | 字符集合中任选一个 | [13579] 匹配单个奇数 |
() 与 | | 分组与或 | (jpg|png) 匹配 jpg 或 png |
国内手机号规则:以 1 开头,第二位是 3–9,总共 11 位。正则写作 1[3-9]\d{9}。拆开读:1 匹配开头,[3-9] 匹配第二位,\d{9} 再来 9 位数字。
如果要从一整段文本里「提取」手机号而不是验证整段,加上单词边界防止匹配到更长的数字串:\b1[3-9]\d{9}\b。如果表单校验要求整串必须就是手机号,前后加上锚点:^1[3-9]\d{9}$,^ 和 $ 分别表示串的开头和结尾。
完整邮箱标准(RFC 5322)复杂到能写满一页纸,实战用简化版足够:^[\w.+-]+@[\w-]+\.[\w.]+$。读法:开头一组字母数字下划线点加减号(用户名),一个 @,域名主体,一个点,顶级域。它放行少数非法地址(如 a..b@x.com),但拦得住绝大多数格式错误——校验邮箱真伪最终还得靠发验证邮件。
<.*> 会把「<a>文本</a>」从第一个 < 一路匹配到最后一个 >。在量词后加 ? 变成懒惰模式 <.*?>,就只匹配单个标签;.、+、( 这些符号本身有特殊含义,想匹配它们本身要加反斜杠,如匹配 3.14 写 3\.14;^ $ 只匹配整个文本的首尾,想对每一行生效,需要开启多行标志(多数工具里是一个 m 选项)。匹配只解决「找得到」,配合分组引用的替换才解决「批量改」。核心是:用 () 圈住要保留的部分,替换串里用 $1、$2 引用它们(部分语言用 \1)。
实例:把 2026-10-08 格式的日期批量改成 08/10/2026。匹配式 (\d{4})-(\d{2})-(\d{2}),替换串写 $3/$2/$1——三个分组调换顺序而已,全文几百个日期一次改完。再比如给 markdown 里所有裸链接加超文本:(https?://[^\s)]+) 替换为 [$1]($1),同一份匹配复用两次。
进阶一点的是「查找重复单词」:\b(\w+)\s+\1\b 里 \1 反向引用第一组,能抓出 the the 这类手误。分组引用用熟之后,文本处理效率是纯手工的十倍以上。
问:正则能校验身份证、URL 吗?
能匹配格式,但身份证有校验位算法、URL 的合法组合极多,正则只能挡格式错误,语义正确性要在代码里另行验证。
问:不同语言的正则有区别吗?
核心语法通用,细节有差:JavaScript 不支持反向预查的部分变体,Python 的 re 模块默认不区分大小写需显式开 flag。常用语法在主流引擎里都是一致的。