正则表达式基础:元字符与模式归纳总结
刚开始学正则表达式的时候,我也挺头疼的。那一串符号像天书,你不知道哪个符号管哪个。后来我带团队做金融日志脱敏项目,十几个正则规则堆在一起,跑一遍要好几秒——这时候才意识到:把元字符吃透,比死记硬背一百个例子有用得多。
1. 元字符分类速查
元字符,说白了就是正则里的“动词”和“名词”。它们告诉引擎:你要匹配什么字符、重复几次、从哪里开始。我把常用元字符按功能分了五类,你对照着这张表看,心里就有谱了。
| 类别 | 元字符 | 含义 |
|---|---|---|
| 定位符 | ^ $ \b \B | 匹配行首、行尾、单词边界、非单词边界 |
| 字符类 | . \d \w \s [abc] [^abc] | 匹配任意字符、数字、字母/数字/下划线、空白符、集合内字符、集合外字符 |
| 量词 | * + ? {n,m} | 零次或多次、一次或多次、零次或一次、指定次数范围 |
| 分组与捕获 | (…) (?:…) \1 (?|…) | 捕获分组、非捕获分组、反向引用、分支重置 |
| 断言 | (?=…) (?!…) (?<=…) (?<!…) | 顺序肯定、顺序否定、逆序肯定、逆序否定 |
我的习惯是:先把定位符和字符类写明白,量词放在最后调。见过太多新手一上来就写
.*,结果匹配了不该匹配的内容,回溯还把引擎锁死了。
2. 模式匹配的核心逻辑
正则引擎是怎么“跑”起来的?简单说就是:从左到右扫描目标字符串,拿模式里的每个“零件”去尝试匹配。匹配不上就回溯——退到上一个成功的位置,换一条路径继续试。回溯次数一多,性能就崩了。
关键点就两个:
- 贪婪 vs 非贪婪:
*和+默认贪婪——能多吃就多吃。加个?变成*?,就改成了“够用就停”。我在做身份证号提取时踩过坑:用、+?\d{18}配得好好的,换成\d*就全乱了。其实就是没加边界限定,引擎跑到结尾才发现不对,又回头重试。 - 锚点与多行模式:
^默认匹配字符串开头,加上m标志后匹配每一行的开头。你想想看,日志文件里每行一条记录,不打开多行模式,^ERROR只能逮住第一条。
// 例子:提取所有以 "PID:" 开头的行
// 没加 m flag → 只匹配第一行
const single = /^PID:\s+\d+/;
// 加了 m flag → 匹配每一行
const multi = /^PID:\s+\d+/gm;
我曾经在生产环境里用一个超长的正则去清洗用户输入,没加
s 标志(让 . 匹配换行符),结果多行文本里的换行全被当成匹配结束,漏了十几个关键字段。记住:. 默认不匹配 \n,需要时主动加 s。
3. 实战避坑指南
下面几个场景是我在项目中反复遇到的,你也可以作为自检清单:
- 量词后紧跟其他字符:
\d+abc和\d+?abc完全不一样。前者\d+吞掉所有数字,再吐出来给abc做匹配;后者\d+?只吞第一个数字,然后立即尝试abc。匹配结果可能迥异。 - 转义要彻底:匹配 IP 地址时写
\d{1,3}\\.\d{1,3}\\.\d{1,3}\\.\d{1,3},点号前的反斜杠不能省。很多人写\.写成.,结果配出了1921681—— 因为.能匹配任意字符。 - 字符类内部的特殊规则:在
[]里,^放在开头表示取反,放在别处就是普通字符;-在中间表示区间,比如[a-z];]必须放在字符类最开头才不会出错。我没少在这上面吃过亏。
元字符分类脑图
说实话,正则这东西,用多了就熟了。但我有个建议:别上来就写几十个字符的长模式。先拆成测试件,把每一段都跑通,再用分组拼起来。我在某支付接口的敏感数据识别里就是这么干的——“银行卡号 + 有效期 + CVV”各自先验,最后组合,定位准确率从 82% 提到了 97%。
嗯,说到这里,其实你已经把元字符和模式匹配的核心逻辑摸透了。剩下的就是多写、多测、多复盘。碰到复杂的场景,用在线工具逐帧调试,看着回溯路径你就能理解引擎在想什么了。