首页 › tutorials › 造正则Skill:描述直转正则并自验证

Claude Code Skills 开发实战:从零造一个会自我验证的正则生成 Skill

概述

本教程面向已装好 Claude Code、想从「会用别人写的 Skill」升级到「自己造 Skill」的开发者。你将掌握 2026 版 Skill 的完整骨架——三个存放目录的区别、SKILL.md 的 15 个 frontmatter 字段、进度披露(progressive disclosure)的拆分原则,并最终亲手造出一个 regex-forge 技能:输入一句自然语言,输出一条已被脚本验证过、可直接复制的正则表达式。适合做过一轮 Claude Code 入门、能看懂 Markdown 与少量 JavaScript 的读者。

前置条件


一、先搞清楚:Skill 到底是什么、放哪儿

一个 Skill 在磁盘上就是一个文件夹,里面至少有一个带 YAML frontmatter 的 SKILL.md。Claude Code 启动时扫描这些文件,把它们的 name 和 description 注册进自己的「技能目录」。当对话内容命中某条描述,或你手动敲 /技能名,对应的指令才会被加载进上下文执行。

存放位置有三档,优先级从高到低:

目录 作用域 是否进 git 典型用途
~/.claude/skills/ 用户全局,所有项目可用 — 个人跨项目复用的小工具
<项目>/.claude/skills/ 项目级,团队共享 是(建议) 团队规范、项目专属流程
<项目>/.claude/skills.local/ 项目级,仅自己 否(gitignore) 个人临时实验

命名规则:技能名只能小写字母、数字、连字符,最长 64 字符,目录内唯一。我们这次造的叫 regex-forge,放在项目级 .claude/skills/regex-forge/。

操作说明:

mkdir -p .claude/skills/regex-forge/scripts
mkdir -p .claude/skills/regex-forge/references

预期结果:得到如下骨架——

.claude/skills/regex-forge/
├── SKILL.md          # 入口,唯一会被默认读进上下文的文件
├── scripts/          # 进度披露:可执行脚本,按需调用
└── references/       # 进度披露:参考资料,按需加载

常见问题:


二、写 frontmatter:15 个字段里,真正决定成败的只有两个

frontmatter 是 SKILL.md 顶部被 --- 包住的 YAML 块。2026 版规范里它有多达 15 个字段,但对绝大多数 Skill 来说,description 决定「能不能被触发」,allowed-tools 决定「跑得顺不顺」,其余按需。

2.1 description——整个 Skill 最该花心思的一行

它驱动自动触发:模型是靠读这段话来判断「现在该不该把这个技能拽进来」。官方给的有效公式是:

[动词短语:它做什么]。Use when [触发短语]。

对比:

# ❌ 模糊,模型不知何时用
description: 正则助手

# ✅ 具体,触发词密集
description: Build and test a regular expression from a natural-language description of what should match or be rejected. Use when the user asks for a regex, a pattern, to match/validate/extract emails, phone numbers, hashtags, or any text pattern.

注意:description 加上可选的 when_to_use,在技能目录里被截断到 1536 字符。宁可具体不可啰嗦。

2.2 allowed-tools——给脚本开绿色通道

我们的技能要跑 node 做验证。如果不声明,每次执行都会弹权限确认,打断节奏。声明后,技能激活期间这些工具免确认:

allowed-tools:
  - Bash(node:*)
  - Read

铁律:尽量收窄。 写 Bash(node:*) 而不是 Bash,写 Read(./src/**) 而不是 Read。松散的权限等于在每个加载该技能的项目里预授权,是安全隐患。而且全局 deny 永远优先,allowed-tools 只能「加」,不能「绕」。

2.3 完整的 frontmatter

---
name: regex-forge
description: Build and test a regular expression from a natural-language description of what should match or be rejected. Use when the user asks for a regex, pattern, or validation rule (match emails, validate phone numbers, extract hashtags).
argument-hint: <what-to-match> [--tests="mustMatch;mustNotMatch"]
allowed-tools:
  - Bash(node:*)
  - Read
---

字段小结:

常见问题:


三、写 body:把「聪明的指令」拆成「笨但可靠的步骤」

body 是 frontmatter 之后的正文。原则是可执行、可校验——把模糊的「帮我写正则」拆成模型能照做的清单,并强制走验证脚本。

# Regex Forge

把一句自然语言的匹配需求,变成一条**已被测试通过**的正则。

## 步骤

1. 读懂 `$ARGUMENTS` 或对话,明确:什么必须匹配?什么必须**不**匹配?
2. 写出**一条** JavaScript 风格正则。优先选满足需求的最窄模式。仅当需求隐含整串校验时才加 `^`/`$` 锚点或 `\b`。
3. **返回前必须先验证**,运行内置测试器:

   ```bash
   node scripts/regex-tester.js "<PATTERN>" "<必须匹配,samples>" "<必须不匹配,samples>"
   ```

   脚本输出 `PASS` 才算数,否则逐条列出失败样本。未得 `PASS` 前不要向用户展示正则。失败就改模式重跑。

4. 通过后,输出:正则代码块 + 每段(锚点/分组/量词)的一句话解释 + 测试证据。
5. 涉及进阶构造(后行断言、Unicode、反向引用)时,查阅 `references/regex-cookbook.md` 并注明引用的小节。

预期结果:模型拿到这段 body 后,行为从「直接甩一个可能错的正则」变成「生成→自测→必要时改→再给」。这正是 Skill 相比纯 prompt 的价值:把流程固化下来。

常见问题:


四、加 bundled 脚本:进度披露的关键一环

SKILL.md 默认加载,但 scripts/、references/ 不会——它们是按需才被读进来。这就是「进度披露」:入口保持精简,重资源用到才取,省 token、保聚焦。

新建 scripts/regex-tester.js(注意把 g 标志剥掉,避免 test() 的有状态陷阱):

#!/usr/bin/env node
// 校验一条正则:必须匹配的全匹配,必须不匹配的全不匹配。
// 用法: node regex-tester.js "<pattern>" "<must,match>" "<must,not,match>"
const [, , patternStr, matchStr = "", nomatchStr = ""] = process.argv;
if (!patternStr) { console.error("FAIL: no pattern"); process.exit(2); }

// 支持 /pattern/flags 形式,统一拆出 source,并去掉 g 以保证 test() 无状态
let source = patternStr, flags = "";
const m = patternStr.match(/^\/(.+)\/([gimsuy]*)$/);
if (m) { source = m[1]; flags = m[2].replace(/g/g, ""); }

let re;
try { re = new RegExp(source, flags); }
catch (e) { console.error("FAIL: invalid regex -> " + e.message); process.exit(2); }

const must    = matchStr  ? matchStr.split(",")  : [];
const mustNot = nomatchStr? nomatchStr.split(","): [];
const fails = [];
for (const s of must)    if (!re.test(s)) fails.push(`should MATCH:    "${s}"`);
for (const s of mustNot) if ( re.test(s)) fails.push(`should NOT match: "${s}"`);

if (!fails.length) {
  console.log(`PASS — /${re.source}/${flags} | ${must.length} positive, ${mustNot.length} negative`);
  process.exit(0);
}
console.log("FAIL:");
fails.forEach(f => console.log("  - " + f));
process.exit(1);

预期结果——在项目根目录手测一次:

node .claude/skills/regex-forge/scripts/regex-tester.js \
  '^\d{4}-\d{2}-\d{2}$' \
  '2026-07-09,1999-12-31' \
  '26-07-09,2026/07/09'
# PASS — /^\d{4}-\d{2}-\d{2}$/ | 2 positive, 2 negative

脚本返回 PASS,正则可信;改个故意错的模式则会列出哪条样本挂了。

常见问题:


五、加 references:把「偶尔才用」的知识按需加载

进阶构造不必塞进 SKILL.md,放进 references/regex-cookbook.md,body 第 5 步提示模型「需要时去查」即可:

# Regex Cookbook(按需查阅,仅在用到进阶构造时加载)

- 后行断言:匹配前面是 `$` 的 `foo` → `(?<=\$)foo`
- 命名分组:`(?<year>\d{4})-(?<month>\d{2})` → `match.groups.year`
- Unicode 属性:任意文字 `\p{L}+`(需 `u` 标志)
- 反向引用:连续重复字符 `(\w)\1`
- 锚点取舍:`^...$` 用于表单整串校验;`\b` 用于从长文本里定位词

这样 SKILL.md 始终轻量,复杂知识按需出现,上下文不爆。


六、发现、触发与自测:确认它真的能用

保存好三份文件后,新开一个 Claude Code 会话(老会话不会热重载技能目录)。两种触发方式:

  1. 手动:敲 /regex-forge 匹配中国大陆手机号,补全菜单应出现你写的 argument-hint。
  2. 自动:直接说「帮我写个匹配邮箱的正则」,模型读到 description 里的触发词,应自行激活该技能。

验证「是否被加载」的窍门:在对话里问「你现在激活了哪些技能」,或观察它有没有去调用 node .../regex-tester.js——调用了,就说明 body 生效了。

常见问题:


实战案例:一句话产出可上线的邮箱校验正则

完整跑通这个 Skill。用户输入:

/regex-forge 校验公司邮箱:用户名是字母数字下划线,域名是 xxx.com,要整串匹配,并给我两组测试

技能被激活后,模型按 body 执行:

  1. 理解需求:必须匹配 名@xxx.com、整串、用户名限 [A-Za-z0-9_]。
  2. 生成候选:^[A-Za-z0-9_]+@xxx\.com$
  3. 调脚本自测:
node scripts/regex-tester.js '^[A-Za-z0-9_]+@xxx\.com$' '[email protected],[email protected]' '[email protected],[email protected],空格 @xxx.com'
# PASS — /^[A-Za-z0-9_]+@xxx\.com$/ | 2 positive, 3 negative
  1. 通过,输出最终答复:
✅ 正则:/^[A-Za-z0-9_]+@xxx\.com$/

逐段解释:
- ^ ... $   整串校验,前后不允许多余字符
- [A-Za-z0-9_]+  用户名:字母/数字/下划线,至少 1 位
- @xxx\.com  字面域名(. 被转义,只匹配点号)

测试证据(脚本 PASS):通过 2 条正例、3 条反例。

整个链路里,模型没把未经测试的正则交给你——脚本兜住了正确性。这就是把 Skill 做成「自带质检」的好处。


工作流程图

flowchart TD
    A["用户:帮我写个匹配邮箱的正则"] --> B{"description 命中触发词?"}
    B -- 否 --> Z["走常规对话"]
    B -- 是 --> C["加载 SKILL.md 进上下文(默认全量)"]
    C --> D["解析 $ARGUMENTS / 参数"]
    D --> E["按 body 步骤生成候选正则"]
    E --> F["Bash: node scripts/regex-tester.js"]
    F --> G{"脚本输出 PASS?"}
    G -- 否 --> E
    G -- 是 --> H["返回正则 + 解释 + 测试证据"]
    C -. 用到进阶构造时 .-> R["按需加载 references/regex-cookbook.md"]
    style F fill:#e8f5e9
    style G fill:#fff8e1

进阶:再往前走两步

  1. 换模型省成本:正则这类「确定性变换」可加 model: haiku + effort: low,便宜又快;若改造成需要权衡架构的技能,再 model: opus。
  2. 大读取量技能用 fork:若把技能扩成「扫全仓所有日志再总结」,加 context: fork + agent: Explore,让它跑在隔离子代理里,不污染主对话、还省主上下文。
  3. skill-creator 自动脚手架:不想手敲骨架,可直接调用官方的 skill-creator 技能,描述需求即可生成目录与初版 SKILL.md,再把 frontmatter 按本教程精修。

延伸阅读

参考来源

  1. Extend Claude with skills — Claude Code Docs — 官方技能总览,定义了 SKILL.md、三个存放目录与触发机制。
  2. Claude Code Skill Frontmatter: Every YAML Option Explained — 逐字段拆解 15 个 frontmatter 字段的默认值、用法与最佳实践(2026-04 更新)。
  3. SKILL.md Format Explained — frontmatter 各字段、body 结构与 allowed-tools 写法的实操详解。
  4. Claude Code Skills Structure and Usage Guide (gist) — 技能如何被格式化为 Skill 工具提示并参与自动触发。
  5. Claude Skills Tutorial: Build Your First Skill (TECHSY) — 从零创建首个 Skill 的入门范例,可作为本教程的前置热身。

训练营适用性评估

[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。

51学通信知识星球海报-扫码加入