写正则并解释
连边界情况和反例一起给
帮我写一个正则:匹配 [描述需求]。要求:1)给出正则表达式;2)逐个片段解释含义;3)列出 3 个能匹配的例子和 3 个不该匹配的例子;4)指出这个正则在什么极端输入下会回溯爆炸,以及如何避免。
适合什么场景
- 校验有明确规范的输入(订单号、日志行、固定格式的设备号),边界可以穷举。
- 要从海量日志里抽字段,样本多到不能人工核对。
不适合的场景
- 要解析 JSON、HTML 或任何嵌套结构:用 parser,正则会在嵌套上崩。
- 输入格式本身没定(用户随手填的地址):先定格式,否则正则只是把模糊变成错误。
示例
输入
需求:匹配中国内地手机号,允许 +86 / 86 前缀,允许号码中用空格或短横分隔,不接受其他字符。 样本:+86 138 0013 8000、13800138000、8613800138000、12800138000(应拒绝)、+86 138-0013-8000
你会得到
先给「归一化 + 校验」两步:剥掉前缀和分隔符后匹配 `^1[3-9]\d{9}$`,而不是把分隔符织进一个巨型正则。然后逐段解释、给 3 个应匹配和 3 个应拒绝的例子,最后指出现有写法若用 `(\d+)+` 会在长数字串上回溯爆炸,固定长度量词可以避免。常见误用
- 用正则解析 HTML 或嵌套 JSON,遇到一层嵌套就失效,还可能把半截内容当成匹配。
- 只测「应该匹配」的例子,不测不该匹配的,于是 `.*` 看起来什么都能过。
可以这样改
- 加「给出不使用回溯的等价写法(RE2 或原子组)」,在日志管道里能避免一个恶意输入打满 CPU。
- 加「列出这个正则明确不支持的情况」,避免你误以为它覆盖了全部输入。