Use Cases (更新: 2026/6/2)

用 Claude Code 编写、测试和审查正则表达式

用 Claude Code 生成、调试和审查正则表达式,覆盖邮箱、电话、日志抽取、命名捕获和常见陷阱。

用 Claude Code 编写、测试和审查正则表达式

正则表达式最容易出错的地方,不是符号太难背,而是需求没有说清楚。一个能匹配 user@example.com 的表达式,可能会误拒 user+tag@sub.example.co.jp,也可能误放 user@.com。如果后来又增加几个捕获组,代码审查也会变得很痛苦。

Claude Code 适合把这些模糊要求整理成一套可验证的流程:允许的例子、拒绝的例子、正则表达式、可执行测试和审查清单。正则表达式就是用一组规则描述文本形状的小语言;命名捕获则是给抽取出来的部分取名,例如 timestamprequestId

如果你刚开始使用 Claude Code,可以先读 Claude Code 入门指南。想把需求写得更稳定,可以配合 5 个更好的提示词技巧。官方资料建议同时打开 Claude Code overviewMDN JavaScript 正则表达式参考

工作流

flowchart LR
  A["应该匹配的例子"] --> C["交给 Claude Code"]
  B["不应该匹配的例子"] --> C
  C --> D["正则和辅助函数"]
  D --> E["Node.js 测试"]
  E --> F["审查陷阱"]

不要只说“写一个邮箱 regex”。要告诉 Claude Code 这是用于验证、抽取、替换还是日志分析。例子越具体,测试就越像真实合同。

第一个提示词

请为邮箱地址、日本电话号码和应用日志创建一个 JavaScript 正则辅助模块。

要求:
- 可以直接在 Node.js 中运行
- 允许 user+tag@sub.example.co.jp
- 拒绝 user..name@example.com 和 user@.com
- 允许 090-1234-5678, 03-1234-5678, 05012345678
- 用命名捕获从日志中取出 timestamp, level, service, requestId, message
- 使用 node:test 添加测试
- 如果某些规则不应该只靠正则完成,请解释原因

这里的重点是限制范围。完整的邮箱规范很大,注册表单通常不需要也不适合完全实现。更务实的做法是拦住明显错误,再用确认邮件或后端逻辑验证可达性。

示例1: 邮箱、电话和日志辅助模块

把下面代码保存为 regex-helper.mjs,执行 node regex-helper.mjs

import { fileURLToPath } from "node:url";

export const emailRegex =
  /^(?!.*\.\.)[A-Z0-9_%+-]+(?:\.[A-Z0-9_%+-]+)*@(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,63}$/i;

export const emailSearchRegex =
  /[A-Z0-9_%+-]+(?:\.[A-Z0-9_%+-]+)*@(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,63}/gi;

export const normalizedJapanesePhoneRegex = /^0(?:[5789]0\d{8}|[1-9]\d{8,9})$/;

export const looseJapanesePhoneSearchRegex =
  /0\d{1,4}[-\s]?\d{1,4}[-\s]?\d{3,4}/g;

export const appLogRegex =
  /^\[(?<timestamp>\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z)\]\s+(?<level>INFO|WARN|ERROR)\s+(?<service>[a-z][a-z0-9-]*)\s+requestId=(?<requestId>[A-Za-z0-9_-]+)\s+message="(?<message>[^"]*)"$/;

export function isEmail(input) {
  return emailRegex.test(input.trim());
}

export function normalizePhone(input) {
  return input.replace(/[()\s-]/g, "");
}

export function isJapanesePhone(input) {
  return normalizedJapanesePhoneRegex.test(normalizePhone(input));
}

export function extractContacts(text) {
  const emails = [...text.matchAll(emailSearchRegex)]
    .map((match) => match[0])
    .filter(isEmail);

  const phones = (text.match(looseJapanesePhoneSearchRegex) ?? []).filter(
    isJapanesePhone,
  );

  return {
    emails: [...new Set(emails)],
    phones: [...new Set(phones)],
  };
}

export function parseLogLine(line) {
  const match = line.match(appLogRegex);
  if (!match?.groups) return null;

  return {
    timestamp: match.groups.timestamp,
    level: match.groups.level,
    service: match.groups.service,
    requestId: match.groups.requestId,
    message: match.groups.message,
  };
}

if (process.argv[1] === fileURLToPath(import.meta.url)) {
  const text = "Contact: user+tag@sub.example.co.jp / 090-1234-5678";
  const log =
    '[2026-06-02T10:15:30.000Z] ERROR billing-api requestId=req_123 message="payment failed"';

  console.log(extractContacts(text));
  console.log(parseLogLine(log));
}

电话号码先做标准化,再用正则验证。这样可以把 090-1234-5678090 1234 5678 处理成同一种形式。日志解析使用命名捕获,审查时能直接看到 match.groups.requestId,不用猜 match[4] 是什么。

示例2: 用测试固定行为

把下面代码保存为 regex-helper.test.mjs,执行 node --test regex-helper.test.mjs

import test from "node:test";
import assert from "node:assert/strict";
import {
  extractContacts,
  isEmail,
  isJapanesePhone,
  parseLogLine,
} from "./regex-helper.mjs";

test("validates practical email addresses", () => {
  assert.equal(isEmail("user@example.com"), true);
  assert.equal(isEmail("user+tag@sub.example.co.jp"), true);
  assert.equal(isEmail("user..name@example.com"), false);
  assert.equal(isEmail("user@.com"), false);
  assert.equal(isEmail("@example.com"), false);
});

test("validates Japanese phone numbers after normalization", () => {
  assert.equal(isJapanesePhone("090-1234-5678"), true);
  assert.equal(isJapanesePhone("03-1234-5678"), true);
  assert.equal(isJapanesePhone("05012345678"), true);
  assert.equal(isJapanesePhone("123-4567-8901"), false);
  assert.equal(isJapanesePhone("090-123-456"), false);
});

test("extracts contacts from free text", () => {
  assert.deepEqual(
    extractContacts("support: user+tag@example.com, tel: 090-1234-5678"),
    {
      emails: ["user+tag@example.com"],
      phones: ["090-1234-5678"],
    },
  );
});

test("parses application logs with named captures", () => {
  const parsed = parseLogLine(
    '[2026-06-02T10:15:30.000Z] WARN auth-service requestId=req_abc message="retry required"',
  );

  assert.deepEqual(parsed, {
    timestamp: "2026-06-02T10:15:30.000Z",
    level: "WARN",
    service: "auth-service",
    requestId: "req_abc",
    message: "retry required",
  });
});

继续让 Claude Code 运行测试,而不是只生成测试。

运行 node --test regex-helper.test.mjs。
如果测试失败,先说明是正则错了还是测试数据错了,再修改。
如果要放宽邮箱规则,先新增一个允许例子和一个拒绝例子。

示例3: 日志抽取提示词

日志格式由应用控制,因此很适合用正则抽取。

读取 logs/app.log,只抽取 ERROR 行,并把 requestId 和 message 写入 CSV。
使用 regex-helper.mjs 中相同的 appLogRegex。
不能静默丢弃无法解析的行,最后输出数量。
不要把邮箱地址或电话号码写入 CSV。

“无法解析的行”很重要。真实日志里会有旧格式、截断行和紧急调试输出。返回 null 的解析函数,比静默忽略数据的脚本更容易审查。

审查模板

## Regex review request

Files:
- regex-helper.mjs
- regex-helper.test.mjs

Review:
- Are allowed and rejected examples covered by tests?
- Are email, phone, and log responsibilities separated?
- Are named capture names readable?
- Is there any ambiguous repetition that could cause ReDoS?
- Could personal data leak into logs or CSV output?

Output:
- For each issue, include file, line, reason, and suggested fix
- Ask a question instead of guessing when the business rule is unclear
- Run node --test regex-helper.test.mjs after changes

ReDoS 指的是正则在特制输入上耗时异常,可能造成性能故障。只要模式里有多层重复,就应该让 Claude Code 明确检查。

常见陷阱

陷阱更好的做法
只给成功例至少给 3 个拒绝例
到处使用 .*使用明确边界,例如 [^"]*
用带 g 的正则反复 test()验证正则和搜索正则分开
依赖捕获编号使用命名捕获或非捕获组
把正则当成业务验证可达性、存在性和权限交给后端

正则适合整理输入形状和从受控文本里抽取信息。它不能证明邮箱真的能收到邮件,也不能证明电话号码仍在使用。

什么时候不要用正则

Claude Code 的价值不只是写出一个更复杂的正则,也包括提醒你换工具。处理 URL 时,如果要拆出协议、域名、路径、查询参数和 hash,JavaScript 的 URL 类通常比手写正则可靠。处理 JSON 日志时,应该先 JSON.parse,而不是用正则匹配大括号。处理 CSV 时,也不要自己用逗号切分,因为引号、换行和转义规则很容易漏掉。可以在提示词里直接写:“只在纯文本抽取时使用正则;如果平台有更安全的 parser,请优先使用并说明原因。”

在审查时,把问题拆成三层也很有用。第一层是输入形状,正则适合解决。第二层是业务规则,例如这个邮箱域名是否允许注册、这个电话是否属于目标地区。第三层是存储规则,例如是否可以写入日志、分析事件或 CSV 导出。把三层分开后,正则 helper 就不会偷偷变成难以维护的业务策略中心。

对于多语言站点,还要注意本地格式差异。日本电话号码、美国电话号码、印度手机号、欧洲带国家码的号码,不应该用同一个表达式硬套。Claude Code 可以为每个市场生成样例表,但你要明确“本文只验证日本国内号码”或“这里允许 E.164 格式”。范围说得越清楚,生成结果越容易测试,也越不容易误导读者。

如果文章面向初学者,还要把这些限制写在正文里,而不是只藏在代码注释中。读者复制代码前先理解边界,后续咨询和模板销售的信任感也会更高。

转化引导(CTA)

正则改造常常贴近收入路径:线索表单、结账日志、客服录入、资料下载注册。个人练习可以从 免费 Claude Code 速查表 开始;需要可复用提示词和模板,可以看 ClaudeCodeLab 产品;团队要把验证、日志审查和代码审查门禁落地,可以使用 Claude Code 培训与咨询

总结

用 Claude Code 写正则的关键,不是把符号知识完全交给 AI,而是同时给出例子、反例、测试和审查标准。Masa 实测后发现,“请同时生成正则和测试”比“写一个正则”更稳定,尤其能提前发现 user+tag 邮箱、带连字符电话号码和命名日志捕获这类容易回归的问题。

#Claude Code #regular expressions #regex #debugging #testing
免费

免费 PDF: Claude Code 速查表

输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。

我们会妥善保护你的信息,不发送垃圾邮件。

把 Claude Code 变成真正能带来结果的工作流

先领取中文说明的免费 PDF,再进入英文商品页选择合适的教材。如果你需要团队落地、流程设计或内容变现支持,也可以直接咨询。

Masa

关于作者

Masa

专注 Claude Code 实务流程、团队导入和内容转化的工程师。