正则到底在干什么字面匹配不够用,请出元字符锚点:把匹配钉死在开头和结尾捕获组:把数据从文本里抠出来命名组:让正则半年后还能看懂三个真实场景跑一遍两个进阶技巧怎么学,别死背
先说一个很多人都干过的活:从一段乱七八糟的文本里,把日期、时间、日志级别一个个抠出来。
大多数人的第一反应是 split:先按空格切一刀,再按冒号切一刀,切到第四层发现今天的格式变了,前面的代码全白写。
今天要聊的正则表达式,就是专门治这个的。它本质上是一门「描述文本形状」的迷你语言——不用装任何解析库,Python 里 import re 就能用。学会它之后你会发现,很多要写几十行的文本处理,几行就能干完。
工作方式一点都不玄乎:它拿着你给的模式,从左到右一格一格扫描文本,在每个位置试试能不能「套上」这个模子——套得上,就是匹配。
比如想在日志里找 error 这个词,模式就写 r"error"。前面那个 r 是 Python 的原始字符串写法,防止反斜杠被提前转义,写正则时建议都带上。
默认区分大小写,加 re.IGNORECASE 就能忽略。这就是最基础的字面匹配。但真实世界的文本不会长得这么整齐,所以得请出更灵活的工具。
比如日志里的日期 2024-01-15,数字每天都在变,总不能一个个枚举。这时用\d 表示任意数字,{4} 表示重复 4 次,于是 \d{4}-\d{2}-\d{2} 就能匹配所有这种格式的日期。
再比如电话号码,555-1234 和 5555678 两种写法都可能出现,写成 \b\d{3}-?\d{4}\b 就通吃:? 表示前面的字符出现 0 次或 1 次,\b 是单词边界,防止从一长串数字中间硬抠出一段来。
有时你不是要在文本中间随便找,而是要求必须从开头或结尾算起。^ 匹配字符串开头,$ 匹配结尾。
注意 $ 只负责「站在这 个位置」,本身不消耗任何字符。做格式校验时锚点特别有用:检查一行日志是不是以时间戳开头、某个字段是不是纯数字,都得靠它把范围钉死。
前面都在「找」,但数据活里更常做的是「提取」。比如这么一行日志:
这里的 .*? 是非贪婪匹配,后面细说。捕获组的意义在于:非结构化文本直接变结构化字段,这是日志解析里最常用的一招。
捕获组一多,靠位置记「第 3 个组是啥」迟早出错。命名组语法是 (?P<名字>...),取值时用 group('名字'):
好处很实在:以后就算调整组的顺序,代码一行不用改;别人读你的正则,也能一眼看懂每段在抓什么。
场景一:数据清洗。产品编码五花八门——PROD-123、Product 456、prod_789、PR-101,你只想要里面的数字:
场景二:信息提取。客服日志长这样:
场景三:格式校验。验证邮箱别只返回 True/False,最好告诉调用方到底错在哪:
先说前瞻(lookahead)。它是一种零宽断言:只检查某个模式存不存在,但不消耗字符。拿来检查密码强度非常顺手:
在量词后面加个 ? 就变成非贪婪——碰到第一个满足条件的位置就停。处理嵌套或重复结构时,这一字之差就是 bug 和正确之间的距离。
正则不是背出来的,建议按这条路线循序渐进:字面匹配 → 字符类和量词 → 捕获组 → 锚点 → 最后再碰前瞻和非贪婪。
- • 复杂模式先拆成小段,逐段测试确认没问题,再拼起来
- • 调试推荐 regex101.com,能实时高亮匹配结果,还会逐段解释含义
- • 用小规模但覆盖边界的数据测:空字符串、特殊字符、超长文本
说到底,正则的核心不是那堆符号,而是「模式匹配」的思维方式。想通这一点,很多原本要写几十行的文本处理,真的就是几行的事。
你写过最离谱的一条正则有多长?评论区贴出来,看看谁的更能把人看劝退
热门跟贴