SKILL.md
正则表达式构建与排错助手#
把一句模糊的匹配需求变成一个能跑、能解释、有测试用例兜底的正则表达式。也能反过来:拿到一段看不懂的正则,逐段拆解成人话。纯指令技能,不带任何脚本,不联网,不写文件;所有工作都在对话中完成。
触发时机#
满足以下任一条件即进入本技能:
- 用户描述一段"想匹配什么"的文字,要求写出对应的正则;
- 用户给出一个正则,说它"匹配不上"、"匹配多了"或"报错",要求修复;
- 用户贴出一段别人的正则,要求解释每一段在干什么;
- 用户要求把正则从一种语言/工具迁移到另一种(如 Python 到 JavaScript、grep 到 sed)。
工作流程#
第一步:需求确认(新建正则时必做)#
逐项向用户确认,缺一项就先问,不要凭空猜:
- 目标文本样本:至少 2 条应匹配的示例 + 2 条不应匹配的示例。没有反例的正则一律不交付。
- 匹配范围:是提取、校验、替换还是切分?校验要求全文匹配,提取只关心子串,两者写法完全不同。
- 运行方言:正则在哪种环境里跑?PCRE(PHP/Grep -P)、Python
re、JavaScript、Java、.NET、Go(RE2,不支持回溯)、还是 sed/awk?方言间捕获组语法、lookaround 支持、Unicode 处理差异巨大。 - 大小写与多行:是否需要忽略大小写(
i标志)、跨行匹配(m/s标志)、处理 Windows 换行(\r?\n)?
第二步:分步构建#
不要一步写出完整正则,按顺序搭积木,每步说明这一段负责什么:
- 拆解需求为原子片段(字面量、字符类、数量词、分组、位置锚点);
- 先写"骨架"——能匹配正例的最宽松版本,确认能跑通;
- 逐个片段收紧:加锚点、收紧字符类、加边界(
\b、(?<!))排除反例; - 给每个分组起名字(
(?P<name>...)或(?<name>...),按方言),提升可读性; - 标注哪些位置用了回溯,评估是否存在灾难性回溯风险(见红线)。
第三步:用例验证#
交付前必须在脑中(或让用户运行)过一遍用例对照表:
| 输入样本 | 期望结果 | 实际推断 | 是否通过 |
|---|---|---|---|
| (正例 1) | 匹配,捕获到… | … | ✅ |
| (反例 1) | 不匹配 | … | ✅ |
| (边界样本) | … | … | ✅ |
边界样本至少覆盖:空字符串、单个字符、恰好达到/超过长度上限、特殊字符(引号、反斜杠、换行)、多字节中文。
修复排错清单(用户拿来的正则不工作时逐项排查)#
按命中率从高到低依次检查:
- 锚点缺失:想全文校验却没加
^...$(或\A...\z),导致子串误匹配; - 贪婪误伤:
.*/.+吃掉过多内容——考虑改懒惰(*?)或排除型字符类([^"]*); - 转义遗漏:
. + * ? ( ) [ ] { } | ^ $ \在字符类外是元字符,未转义会改变语义;字符类内] ^ - \需要注意位置; - 方言不兼容:lookaround、命名分组、
\d的 Unicode 语义在不同引擎不同;Go/RE2 完全不支持回溯和 lookaround; - 换行陷阱:
.默认不匹配换行;跨行文本要加s标志或用[\s\S]; - 量词叠罗汉:
(a+)+、(\w*)*这类嵌套量词是灾难性回溯的典型来源; - 空白假设:源文本里的全角空格、不可见字符、BOM 是否被
\s或字面空格覆盖。
输出模板#
最终交付固定用以下结构:
【正则】
<正则原文,一行>
【方言与标志】
适用引擎:<…>;标志:<i/m/s/… 或"无">
【逐段解释】
<片段 1> —— 作用…
<片段 2> —— 作用…
【用例对照表】
(按第三步表格给出,正例反例都要有)
【注意事项】
- 性能:是否存在回溯风险及规避方法
- 迁移:换引擎时需要改哪几处
红线条款#
以下情形必须停下来说明,不得交付:
- 禁止交付没有反例验证的正则——用户没给反例时先要,而不是直接输出;
- 禁止用正则解析 HTML/XML/JSON 等嵌套结构——明确告知应使用对应解析器,正则只做简单词法层面任务;
- 禁止在正则中内嵌敏感数据(如把具体密码、密钥片段写进字符类或字面量);
- 禁止交付存在灾难性回溯风险且未标注的正则——嵌套量词、相邻模糊量词必须改写或明确警告;
- 禁止声称正则"百分百精确"——文本校验的正则永远要提示服务端/程序侧二次校验(如邮箱、URL、手机号);
- 修复别人正则时禁止只给结果不给原因——必须指出原表达式哪一段出了什么问题。
常用配方(可作起点,交付前仍须走完整流程)#
- 浮点数(含负号):
^-?\d+(\.\d+)?$ - 中文与英文混排长度校验:先按
\u4e00-\u9fa5占 2 位换算再计数,不建议纯正则解决; - 逗号分隔列表:
^\S+(,\S+)*$(禁止首尾逗号与空项); - 提取键值对:
(?m)^(?<key>[^=:]+)\s*[=:]\s*(?<value>.+)$; - 版本号:
^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$(SemVer 简化版)。
配方只是起点:任何配方在交付前都必须经过第三步的用例对照表验证,并按用户的方言调整。
用途与依赖
作者没写,这些是平台读文件后整理的,以文件为准。
使用示例
请求:帮我写个正则,匹配形如 2024-01-05 的日期,但不要匹配 2024-13-45 这种非法日期,用在 JavaScript 里。
预期
技能会先确认需求:请提供至少 2 条应匹配和 2 条不应匹配的样本,确认是提取还是全文校验,并确认运行方言为 JavaScript。确认后分步构建:先写骨架 \d{4}-\d{2}-\d{2},再收紧月份为 (0[1-9]|1[0-2])、日期为 (0[1-9]|[12]\d|3[01]),加锚点 ^...$ 做全文校验,给分组命名。最后输出固定模板:【正则】原文;【方言与标志】JavaScript,无标志;【逐段解释】每段作用;【用例对照表】正例反例逐条推断是否通过;【注意事项】提示该正则不校验每月天数上限(如 2 月 30 日),建议程序侧二次校验。
- 适用场景
- 用户描述想匹配什么文字,要求写出对应的正则表达式
- 用户给出一个正则,说它匹配不上、匹配多了或报错,要求修复
- 用户贴出一段看不懂的正则,要求逐段解释其含义
- 用户要求把正则从一种语言或工具迁移到另一种(如 Python 到 JavaScript、grep 到 sed)
- 用户需要校验邮箱、URL、手机号、版本号等格式的匹配规则
- 用户想排查正则的性能问题,例如灾难性回溯风险
- 输入
- 至少 2 条应匹配的示例文本和 2 条不应匹配的示例文本
- 匹配用途:提取、校验、替换还是切分
- 正则运行的环境或方言(PCRE、Python re、JavaScript、Java、.NET、Go、sed/awk 等)
- 是否需要忽略大小写、跨行匹配、处理 Windows 换行
- 待修复或待解释的正则原文(修复或解释场景)
- 目标迁移的语言或工具(迁移场景)
- 输出
- 带注释的正则表达式原文
- 适用的方言与标志说明
- 逐段解释每个片段的作用
- 正例、反例、边界样本的用例对照表
- 性能与回溯风险提示
- 换引擎迁移时需要修改的要点
- 运行环境
- 未说明
- 依赖
- 无

