Claude Codeで正規表現を作る方法: メール・電話・ログ抽出をテスト付きで安全に進める
Claude Codeで正規表現を作成・デバッグする実践手順。メール、電話、ログ抽出、テスト、落とし穴まで解説。
正規表現でつまずく原因は、記号を覚えていないことよりも「何を許可して、何を拒否するか」が曖昧なまま書き始めることです。メールアドレス、電話番号、ログ行、URL、CSVの一部など、対象が少し複雑になるだけで、動いているように見えるのに本番データで抜け漏れが出ます。
Claude Codeは、正規表現を丸暗記するための道具ではありません。自然言語で要件を渡し、候補パターン、サンプルデータ、テスト、レビュー観点をまとめて作るための相棒です。正規表現とは、文字列の形を条件で表す小さな言語です。名前付きキャプチャとは、取り出した部分に year や requestId のような名前を付ける書き方です。最初にこの2つを押さえるだけで、読みやすさがかなり変わります。
この記事では、Claude Codeで正規表現を作成・デバッグする流れを、コピペで動くJavaScriptコードと一緒に整理します。対象は初心者ですが、実務で困りやすい「メール」「日本の電話番号」「ログ抽出」「テスト付きレビュー」まで扱います。Claude Codeの基本操作は Claude Code入門ガイド を、依頼文の作り方は Claude Code/Codexプロンプト入門 も合わせて読むとつながります。
公式仕様を確認する入口としては、Claude Code overview と MDNのJavaScript正規表現リファレンス が便利です。Claude Codeは便利ですが、仕様そのものを置き換えるものではありません。
全体像
正規表現をClaude Codeに頼むときは、いきなり「メールのregexを書いて」ではなく、次の順番にします。
flowchart LR
A["許可したい文字列"] --> C["Claude Codeへ依頼"]
B["拒否したい文字列"] --> C
C --> D["正規表現と抽出関数"]
D --> E["Node.jsテスト"]
E --> F["レビューと落とし穴確認"]
この流れの狙いは、正規表現を「雰囲気で通す」作業にしないことです。Claude Codeには、成功例だけでなく失敗例も渡します。たとえば user+tag@example.com は通したい、user@.com は落としたい、ログの requestId は取り出したい、個人情報はログに残したくない、という条件を最初に書きます。
Claude Codeへの最初の依頼
最初のプロンプトは短くても構いませんが、用途と合格条件は入れます。
メールアドレス、日本の電話番号、アプリケーションログを扱う正規表現ヘルパーを作ってください。
条件:
- Node.jsでそのまま動くJavaScriptにする
- メールは 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 で動きます。メール検証、電話番号検証、本文からの連絡先抽出、名前付きキャプチャによるログ抽出を1つにまとめています。
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 = "連絡先: 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-5678 と 090 1234 5678 を別物として扱うより、ハイフンや空白を取り除いてから判定したほうが、正規表現を短く保てます。
ログ抽出では名前付きキャプチャを使っています。match[1]、match[2] のような番号だけに頼ると、あとで正規表現を直したときに取り出す列がずれます。match.groups.requestId のように名前で読むと、Claude Codeのレビューでも人間のレビューでも意図が追いやすくなります。
実例2: node:testで回帰テストを付ける
回帰テストとは、一度直した不具合が戻っていないか確認するテストです。正規表現は1文字変えるだけで挙動が変わるため、テストなしの修正は危険です。次のコードを 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へは、テスト結果まで確認させます。
regex-helper.mjs と regex-helper.test.mjs を作成しました。
node --test regex-helper.test.mjs を実行し、失敗した場合は正規表現かテストデータのどちらが間違っているか説明してから修正してください。
メール仕様を広げる場合は、許可例と拒否例を追加してから変更してください。
この形にすると、Claude Codeが「なんとなく広い正規表現」に逃げにくくなります。テストケースが、実務上の契約になります。
実例3: ログ抽出で正規表現を使う場面
ログ抽出は、正規表現が得意な領域です。たとえば、障害調査で ERROR だけを拾い、requestId を追跡したいとします。Claude Codeには次のように依頼できます。
logs/app.log から ERROR 行だけを抽出し、requestId と message をCSVにするNode.jsスクリプトを作ってください。
ログ形式は regex-helper.mjs の appLogRegex と同じです。
パースできない行は捨てずに件数を最後に表示してください。
個人情報らしきメールアドレスや電話番号はCSVに出さないでください。
ここで大事なのは、抽出できない行の扱いです。正規表現の記事では成功例だけが目立ちますが、実務ではフォーマットが崩れた行、古いアプリのログ、途中で切れたログが混ざります。null を返す設計にしておくと、Claude Codeに「捨てた件数をレポートして」と依頼しやすくなります。
実例4: Claude Codeへのレビュー依頼テンプレート
正規表現は、書いた本人ほど危険に気づきにくいです。最後にClaude Codeへレビューを依頼します。
## Regex review request
対象:
- regex-helper.mjs
- regex-helper.test.mjs
レビュー観点:
- 許可例と拒否例がテストに入っているか
- メール、電話、ログ抽出の責務が混ざりすぎていないか
- 名前付きキャプチャの名前が用途を説明しているか
- ReDoSにつながりやすい曖昧な繰り返しがないか
- 個人情報をログやCSVに出す処理がないか
出力形式:
- 問題があれば、ファイル名、該当行、理由、修正案を出す
- 仕様として判断できない点は、断定せず質問にする
- 修正後に node --test regex-helper.test.mjs を実行する
ReDoSは、正規表現の処理に極端な時間がかかる攻撃や障害のことです。たとえば曖昧な繰り返しを何重にも重ねると、短い入力でも処理が重くなることがあります。Claude Codeには「ReDoSの観点で見て」と明示します。
使い分けの表
| 用途 | 正規表現でよい場面 | 別の方法を選ぶ場面 |
|---|---|---|
| メール検証 | 入力フォームで明らかなミスを落とす | 本当に届くか確認したい |
| 電話番号 | 国内向けフォームで形式をそろえる | 国際番号や通信事業者の厳密判定が必要 |
| ログ抽出 | 形式が固定されたアプリログを読む | JSONログを扱える環境がある |
| URL処理 | 短い抽出や検索 | URLを正確に分解する必要がある |
特にURLは、正規表現だけで頑張りすぎないほうが安全です。JavaScriptなら URL クラスがあります。Claude Codeにも「URLの分解は標準APIを優先し、正規表現は抽出だけに使って」と書くと、壊れにくくなります。
よくある落とし穴
1つ目は、成功例だけで作ることです。user@example.com だけを渡すと、Claude Codeは広すぎる正規表現を出しがちです。拒否例を最低3つ入れてください。
2つ目は、.* を雑に使うことです。.* は「何でも何文字でも」という意味で便利ですが、ログやHTMLのように区切りがある文字列では取りすぎます。"(?<message>[^"]*)" のように、終端を具体的に決めます。
3つ目は、g フラグ付きの正規表現を何度も test() することです。JavaScriptの RegExp は g や y が付くと内部状態を持ちます。検証用と検索用の正規表現を分けると事故が減ります。
4つ目は、キャプチャ番号に依存することです。途中に () を足すと番号がずれます。取り出す目的があるなら名前付きキャプチャを使い、グループ化だけなら (?:...) を使います。
5つ目は、正規表現で業務ルールを完全に表そうとすることです。メールが届くか、電話番号が現在使われているか、ログの requestId がDBに存在するかは、正規表現だけでは分かりません。正規表現は入口の形を整える道具として使います。
現場でよくある失敗は、フォームの入力検証とログ抽出を同じ感覚で扱うことです。フォームでは「ユーザーに直してもらう」ためにエラー文が必要ですが、ログ抽出では「壊れた行を捨てずに件数を残す」ことが大事です。たとえば資料請求フォームで電話番号のハイフンを許可し忘れると、正しい見込み客を落とします。一方で障害ログの抽出でパース不能行を無視すると、あとで「何件落としたのか」が分からず、調査結果を信用できません。Claude Codeに依頼するときは、正規表現そのものだけでなく、失敗時の戻り値、ユーザーに出す文言、ログに残す集計値までセットで書かせると、実務で使える形になります。
収益化につなげるCTA
正規表現の改善は小さな作業に見えますが、問い合わせフォーム、資料請求、決済ログ、サポートログの品質に直結します。まず自分で試すなら 無料チートシート でClaude Codeの依頼テンプレートを手元に置いてください。より実務的なプロンプト集やレビュー手順を整えたい場合は 商品一覧 が入口になります。チームで入力検証、ログ調査、レビュー運用までまとめて導入するなら Claude Code研修・導入相談 で、既存コードに合わせた型を作るのが早いです。
まとめ
Claude Codeで正規表現を作るコツは、記号の知識をAIに丸投げすることではありません。許可例、拒否例、用途、テスト、レビュー観点を先に渡し、生成された正規表現を小さな契約として扱うことです。メール、電話、ログ抽出のような身近な題材でも、テストを付けるだけで保守しやすさは大きく変わります。
この記事で紹介した内容を実際に試した結果、Masaの作業では「正規表現だけを作って」と頼むより、「失敗例とテストを同時に作って」と頼むほうがレビュー時間を短縮できました。特に user+tag のメール、ハイフンあり電話番号、ログの名前付きキャプチャは、テストがないと後から壊れやすい箇所です。Claude Codeにレビュー依頼テンプレートまで渡しておくと、正規表現の便利さを保ちながら、フォームやログ処理の事故を減らせます。
無料PDF: Claude Code はじめてのチートシート
まずは無料PDFで基本コマンドと最初の使い方をまとめて確認してください。登録後はそのままテンプレート集や導入相談にも進めます。
スパムは送りません。登録情報は厳重に管理します。
Claude Codeを仕事で使える形にしませんか?
無料PDFで基礎を固めたあと、すぐ使えるテンプレート集で試し、必要なら業務自動化や導入相談まで進められます。
この記事を書いた人
Masa
Claude Codeの実務活用、導入設計、収益導線改善を検証しているエンジニア。10言語の技術メディアを運営中。
関連書籍・参考図書
この記事のテーマに関連する書籍を楽天ブックスで探せます。
※ 当サイトは楽天市場のアフィリエイトプログラムに参加しています。上記リンクから商品をご購入いただくと、運営者に紹介料が支払われる場合があります。
関連記事
ObsidianメモをCLAUDE.mdに変えるClaude Code運用: 文脈を毎回説明しない仕組み
Obsidianの作業メモからCLAUDE.md用の運用ノートを作り、Claude Codeに安定した文脈を渡す方法。
Claude Code Revenue CTA Routing: 記事からPDF、Gumroad、相談へ送る設計
PVだけで終わらせず、読者の状態に合わせて無料PDF、Gumroad教材、導入相談へ分岐するCTA設計です。
Claude Codeチーム引き継ぎルール: レビュー、権限、収益導線まで渡す実務手順
Claude Codeの作業をチームで渡すための証拠、権限、ロールバック、無料PDF/Gumroad/相談導線の実務ルール。