正则表达式实战:从入门到写出可维护的表达式¶
正则不是背出来的¶
很多教程喜欢列一长串元字符表格,看完一头雾水。正则是"工具",不是"知识"。与其背元字符,不如先明确一个问题:你手里的文本长什么样,你想提取什么。本文从实战场景出发,讲清楚最常用的部分。
一、三十分钟掌握核心语法¶
字符匹配¶
a # 精确匹配字符 a
. # 匹配任意一个字符(换行除外)
[abc] # 匹配 a/b/c 中任意一个
[^abc] # 匹配非 a/b/c 的任意字符
\d # 数字,等价 [0-9]
\w # 单词字符 [A-Za-z0-9_]
\s # 空白符(空格、Tab、换行)
量词¶
a* # 0 个或多个 a(贪婪)
a+ # 1 个或多个 a
a? # 0 个或 1 个 a
a{3} # 恰好 3 个 a
a{2,4} # 2 到 4 个 a
位置锚点¶
^abc # 行首是 abc
abc$ # 行尾是 abc
\bword\b # 单词边界,匹配独立单词 word
分组与或¶
(ab)+ # ab 重复
(https?://) # http 或 https
(?:xxx) # 非捕获分组,只分组不记忆
二、实战一:提取日志中的 IP 和端口¶
日志行:
2026-08-05 10:23:45 ERROR 192.168.1.100:8080 connect timeout
提取 IP:端口:
(\d{1,3}(\.\d{1,3}){3}):(\d+)
但这里有个坑:\d{1,3} 允许 999,需要更严谨的 IP 匹配——不过这在实际中通常够用了。正则是够用就好,不是越严格越好,过度严格的表达式反而难以维护。
三、实战二:匹配 HTML 标签内容¶
<div class="title">产品介绍</div>
<p>这是正文内容</p>
提取标签内文字:
<[^>]+>([^<]+)</[^>]+>
注意:处理 HTML 永远不要用正则做复杂解析,嵌套标签会让正则爆炸。用 BeautifulSoup、lxml 这类专用解析器。正则只适合"结构规整、扁平"的文本。
四、实战三:手机号与邮箱校验¶
# 中国大陆手机号(简化版)
^1[3-9]\d{9}$
# 邮箱(简化版)
^[\w.+-]+@[\w-]+(\.[\w-]+)+$
生产环境做校验时,注意两点:
- 前端校验只是体验优化,后端必须再校验一次
- 校验规则别写死——手机号规则会随号段发布而变,邮箱规则各家也不同。宁可宽松校验 + 发送验证码实测
五、贪婪与懒惰:最容易踩的坑¶
<.+> # 贪婪:尽可能多匹配
<.+?> # 懒惰:尽可能少匹配
对文本 <a>text1</a><b>text2</b>:
- 贪婪
<.+>会匹配整个字符串 - 懒惰
<.+?>会分别匹配<a>和</a>
遇到"匹配多了"的问题,先想想是不是贪婪导致的。
六、写可维护正则的五个习惯¶
- 加注释:很多语言支持
(?x)忽略空白模式或#注释 - 拆小块:复杂表达式拆成多个变量再组合,例如
ip = r"(...)"然后full = ip + ":" + port - 用命名分组:
(?P<ip>...)或(?<ip>...),提取结果按名字取,不按索引 - 先测试再上线:用 regex101、regexr 等在线工具,准备好正例反例测试集
- 控制回溯:
(a+)+这类嵌套量词遇到不匹配文本可能产生灾难性回溯,改用原子组(?>...)或省略嵌套
七、各语言使用速览¶
# Python
import re
m = re.search(r"(\d+)", "abc123")
m.group(1) # '123'
# grep
grep -E 'error|fail' app.log
# sed 替换
sed -E 's/(\d{4})-(\d{2})-(\d{2})/\3-\2-\1/' dates.txt
# awk 提取字段
awk '{print $1, $3}' access.log
结语¶
正则的入门曲线并不陡——掌握本文的字符、量词、锚点、分组四块就够覆盖 80% 场景。剩下的,遇到具体问题再查具体语法。把正则当字典用,而不是当课文背,是最快的学习方式。