2026年版 ToolShare Lab / Guide

正規表現入門ガイド
Web制作で使えるパターン20選

「メールアドレスの検証をしたい」「ログから特定のパターンを抽出したい」「HTMLタグを一括置換したい」——そんな場面で必ず登場する正規表現。難しそうに見えるが、基本ルールさえ覚えれば開発・テスト・データ整形の効率が劇的に上がる。この記事では基本メタ文字の解説に加え、Web制作の実務で即使えるパターン20選、JavaScriptでの実践コード例、正規表現の落とし穴と対策まで網羅した。

読了時間: 約20分 更新日: 2026年3月16日

この記事のパターンをすぐ試せる

当サイトの正規表現テスターでパターンをリアルタイム検証できる。データはブラウザ内で処理されるため、ログや個人情報を含むテストデータも安全に扱える。

正規表現(Regular Expression)とは、文字列のパターンを記号で表現する記法で、検索・置換・バリデーションに使われる。基本メタ文字は .(任意の1文字)、*(0回以上)、+(1回以上)、?(0か1回)、[](文字クラス)の5つ。JavaScriptでは /パターン/フラグ のリテラル記法か new RegExp() で生成し、test()・match()・replace()メソッドで活用する。

正規表現とは

正規表現(Regular Expression、略して regex または regexp)は、文字列のパターンを表現するための記法だ。特定の文字の並びを「パターン」として定義し、文字列の検索・抽出・置換・バリデーションを柔軟かつ効率的に行える。

どんな場面で使うか

正規表現はプログラミングに限らず、テキストエディタやコマンドラインツール(grep、sed、awk)でも日常的に使われる。具体的な場面を挙げる。

Point

正規表現はほぼすべてのプログラミング言語でサポートされており、一度習得すれば言語をまたいで応用が利く。構文に若干の差異はあるが、コアとなる考え方は共通だ。

基本メタ文字一覧

正規表現では通常の文字に加え、特別な意味を持つ「メタ文字」を使う。まず頻出の10個を頭に入れておけば、実務のほとんどのケースに対応できる。

メタ文字 意味 マッチする文字列
. 任意の1文字(改行以外) a.c abc, aXc, a1c など
* 直前の要素が0回以上繰り返す ab*c ac, abc, abbc, abbbc など
+ 直前の要素が1回以上繰り返す ab+c abc, abbc(ac は非マッチ)
? 直前の要素が0回または1回 colou?r color, colour
^ 行頭にマッチ ^Hello "Hello world"(先頭から始まる行)
$ 行末にマッチ world$ "Hello world"(末尾で終わる行)
[] 文字クラス(いずれか1文字) [aeiou] a, e, i, o, u のいずれか
() グループ化・キャプチャ (ab)+ ab, abab, ababab など
| OR(選択) cat|dog cat または dog
\ エスケープ(次の文字を文字通りに解釈) \. ピリオド文字そのもの

注意

メタ文字そのものを検索したいときはバックスラッシュでエスケープする。たとえばピリオド(.)を文字として検索するには \. と書く。( ) [ ] { } ^ $ * + ? | \ / などは要エスケープ。これを忘れて意図しないマッチが発生するのは初心者あるあるだ。

文字クラス(\d, \w, \s, \b)

よく使う文字のグループには省略記法の「定義済み文字クラス」が用意されている。[] でいちいち書くより大幅に簡潔になるため、積極的に使いたい。

記法 意味 同等の表現 大文字(否定形)
\d 数字(0〜9) [0-9] \D(数字以外)
\w 単語文字(英数字+アンダースコア) [a-zA-Z0-9_] \W(単語文字以外)
\s 空白文字(スペース・タブ・改行など) [ \t\n\r\f\v] \S(空白以外)
\b 単語境界(単語の開始・終了位置) \B(単語境界以外)
\t タブ文字
\n 改行文字(LF)

文字クラスの範囲指定

[] 内では - を使って範囲を指定できる。^ を先頭に置くと否定クラス(「〜以外」の意味)になる。

[a-z] // 小文字アルファベット [A-Z] // 大文字アルファベット [0-9] // 数字 [a-zA-Z] // 大文字・小文字のアルファベット [^0-9] // 数字以外(否定クラス) [a-z0-9_-] // 小文字・数字・アンダースコア・ハイフン

量指定子

量指定子(Quantifiers)は直前の要素が「何回繰り返すか」を指定するものだ。* + ? の3つが基本で、さらに具体的な回数も指定できる。

量指定子 意味 マッチ例
* 0回以上 \d* ""(空), "1", "123"
+ 1回以上 \d+ "1", "123"(空は非マッチ)
? 0回または1回 \d? ""(空), "1"
{n} ちょうどn回 \d{4} "2026"(4桁の数字)
{n,} n回以上 \d{3,} "123", "1234", "12345"…
{n,m} n回以上m回以下 \d{2,4} "12", "123", "1234"

最長マッチと最短マッチ

デフォルトの量指定子は「最長マッチ(greedy)」で、できるだけ多くの文字にマッチしようとする。量指定子の後に ? を付けると「最短マッチ(lazy)」に切り替わり、できるだけ少ない文字にマッチするようになる。

// 対象文字列: "<b>太字</b>" /<.+>/ → "<b>太字</b>" 全体にマッチ(最長) /<.+?>/ → "<b>" だけにマッチ(最短)

Point

HTMLタグのパターンを書くときは最短マッチ(+?*?)を使うことが多い。ただし複雑なHTMLのパースには正規表現より専用のパーサを使うほうが安全だ。

グループ化とキャプチャ

括弧 () を使うと複数の要素を一つのグループとして扱える。グループ化には「繰り返し単位の指定」と「キャプチャ(一致した部分の取り出し)」という2つの役割があり、これを使いこなせると正規表現が一段と強力になる。

グループ化で繰り返し単位を指定

/(ab)+/ → "ab", "abab", "ababab" にマッチ /(ha){2,}/ → "haha", "hahaha" にマッチ("ha" が2回以上)

キャプチャグループ

グループ化した部分はキャプチャグループとして後から参照できる。日付フォーマットの変換など、マッチ結果を加工する処理でよく使うパターンだ。

// JavaScript での例 const date = "2026-03-16"; const match = date.match(/(\d{4})-(\d{2})-(\d{2})/); // match[1] → "2026"(年) // match[2] → "03"(月) // match[3] → "16"(日) // 置換での参照($1, $2 でグループを参照) "2026-03-16".replace(/(\d{4})-(\d{2})-(\d{2})/, "$1年$2月$3日") // → "2026年03月16日"

非キャプチャグループ

キャプチャせずにグループ化だけしたい場合は (?:...) を使う。不要なキャプチャを省くとパフォーマンスが向上するため、取り出す必要のない括弧は非キャプチャグループにする習慣をつけておくといい。

/(?:http|https):\/\// // "http://" または "https://" にマッチ // http/https の部分はキャプチャしない

先読み・後読み

特定のパターンの「前後に何があるか」を条件として使う「ゼロ幅アサーション」も強力だ。一致した文字自体はキャプチャせず、位置だけを判定できる。

記法 種類 意味
(?=...) 肯定先読み 直後に指定パターンがある位置
(?!...) 否定先読み 直後に指定パターンがない位置
(?<=...) 肯定後読み 直前に指定パターンがある位置
(?<!...) 否定後読み 直前に指定パターンがない位置

Web制作でよく使う正規表現パターン20選

ここからは実務で即使えるパターンを20個まとめた。各パターンにはマッチ例と簡潔な解説を添えている。そのままコピーして正規表現テスターで動作確認しながら、構造を少しずつ読み解いていくと身につきやすい。なお、メールアドレスのパターンについては後述のFAQに補足があるので合わせて確認してほしい。

バリデーション系

1. メールアドレス

^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$ // マッチ例: user@example.com / test.user+tag@example.co.jp // 非マッチ: user@.com ✗ / @example.com ✗

正規表現テスターで試す →

2. 電話番号(日本・固定電話&携帯)

^0[0-9]{1,4}-?[0-9]{1,4}-?[0-9]{3,4}$ // マッチ例: 03-1234-5678 / 09012345678 / 0120-123-456 // 非マッチ: 1234-5678 ✗(先頭が0でない)

正規表現テスターで試す →

3. 携帯番号(日本)

^0[789]0-?\d{4}-?\d{4}$ // マッチ例: 090-1234-5678 / 08012345678 / 070-9876-5432 // 非マッチ: 03-1234-5678 ✗(固定電話は非マッチ)

正規表現テスターで試す →

4. 郵便番号(日本)

^\d{3}-?\d{4}$ // マッチ例: 100-0001 / 1000001 (ハイフン省略可) // 非マッチ: 10-0001 ✗ / 100-00001 ✗

正規表現テスターで試す →

5. URL

^https?:\/\/[\w\-]+(\.[\w\-]+)+([\w\-.,@?^=%&:\/~+#]*)?$ // マッチ例: https://example.com / http://sub.example.co.jp/path?q=1 // 非マッチ: ftp://example.com ✗ / example.com ✗(プロトコルなし)

正規表現テスターで試す →

6. IPアドレス(IPv4)

^(\d{1,3}\.){3}\d{1,3}$ // マッチ例: 192.168.1.1 / 10.0.0.255 // 注: 簡易版。厳密に0-255の範囲をチェックするにはより複雑なパターンが必要

正規表現テスターで試す →

テキスト処理系

7. HTMLタグ除去

<\/?[^>]+(>|$) // "<p>Hello <b>World</b></p>" → "Hello World" // 注: 単純な除去向け。複雑なHTMLには専用パーサを推奨

正規表現テスターで試す →

8. 空白行の削除

^\s*$\n // 空白のみの行(スペース・タブ含む)を丸ごと削除 // VS Codeの正規表現検索でも使える(mフラグ有効時)

正規表現テスターで試す →

9. 先頭・末尾の空白除去(トリム)

^\s+|\s+$ // " hello world " → "hello world" // JavaScriptでは str.trim() でも可能だが、正規表現なら部分的な制御もできる

正規表現テスターで試す →

10. 全角スペースの検出

\u3000 // 全角スペースを検出して半角スペースに置換するケースで使う // 日本語テキストの整形時に頻出

正規表現テスターで試す →

11. 連続する空白を1つに

\s{2,} // "hello world" → "hello world"(置換先を半角スペース1つに) // HTML整形やテキストのクリーニングに便利

正規表現テスターで試す →

抽出系

12. YouTube動画ID

(?:youtube\.com\/watch\?v=|youtu\.be\/)([a-zA-Z0-9_-]{11}) // マッチ例: https://www.youtube.com/watch?v=dQw4w9WgXcQ → ID: dQw4w9WgXcQ // マッチ例: https://youtu.be/dQw4w9WgXcQ → ID: dQw4w9WgXcQ // キャプチャグループ1に動画IDが入る

正規表現テスターで試す →

13. X(Twitter)ユーザー名

@([a-zA-Z0-9_]{1,15}) // マッチ例: @toolsharelab → ユーザー名: toolsharelab // X(旧Twitter)のユーザー名は1〜15文字の英数字とアンダースコア

正規表現テスターで試す →

14. ハッシュタグ

#([^\s#]+) // マッチ例: #Web制作 → タグ: Web制作 / #frontend → タグ: frontend // 日本語ハッシュタグにも対応

正規表現テスターで試す →

15. 日付(YYYY-MM-DD形式)

\d{4}-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12]\d|3[01]) // マッチ例: 2026-03-16 / 2026-12-31 // 非マッチ: 2026-13-01 ✗ / 2026-00-10 ✗

正規表現テスターで試す →

16. 金額(日本円)

¥?[\d,]+円? // マッチ例: ¥1,000 / 1500円 / ¥12,345円 / 500 // 請求書やECサイトのテキストから金額を抽出する場面で使える

正規表現テスターで試す →

バリデーション系(応用)

17. パスワード強度チェック(8文字以上・英数字混在)

^(?=.*[a-zA-Z])(?=.*\d)[a-zA-Z\d\W]{8,}$ // マッチ例: Pass1234 / myP@ss99 // 非マッチ: password ✗(数字なし)/ 12345678 ✗(英字なし)

正規表現テスターで試す →

18. クレジットカード番号(16桁)

^\d{4}[\s\-]?\d{4}[\s\-]?\d{4}[\s\-]?\d{4}$ // マッチ例: 1234-5678-9012-3456 / 1234 5678 9012 3456 // 非マッチ: 1234-5678-901 ✗(桁数不足)

正規表現テスターで試す →

置換系

19. カンマ区切り数値への変換

(\d)(?=(\d{3})+(?!\d)) // 置換先: $1, // "1234567" → "1,234,567" // 金額表示のフォーマットに使える

正規表現テスターで試す →

20. キャメルケースからスネークケースへの変換

([a-z])([A-Z]) // 置換先: $1_$2(さらに全体を小文字に変換) // "camelCase" → "camel_Case" → "camel_case" // CSS変数やDB列名の変換に使える

正規表現テスターで試す →

日本語文字の検出

Web制作では日本語テキストの検出やバリデーションも頻出する。Unicode範囲指定を使ったパターンも覚えておこう。

// ひらがな [\u3041-\u3096] // カタカナ [\u30A1-\u30FA] // 漢字(CJK統合漢字) [\u4E00-\u9FFF] // 日本語全般(ひらがな・カタカナ・漢字) [\u3040-\u309F\u30A0-\u30FF\u4E00-\u9FFF]

ツールで効率化

上記のパターンはすべて当サイトの正規表現テスターで動作確認できる。パターンをコピーしてテスターに貼り付け、テスト文字列を入力するだけでマッチ結果がリアルタイムに表示される。

JavaScriptでの正規表現の使い方

Web制作において最も使用頻度が高いJavaScriptでの正規表現の使い方を詳しく解説する。リテラル記法からメソッドの使い分け、フラグの意味、ES2018で追加された名前付きキャプチャグループまで、実務で必要な知識をまとめた。

正規表現の2つの記法

// リテラル記法(パターンが固定の場合に推奨) const regex = /\d{3}-\d{4}/; // コンストラクタ記法(動的にパターンを生成する場合) const keyword = "hello"; const regex2 = new RegExp(keyword, "gi"); // 注意: コンストラクタ記法ではバックスラッシュを二重にする const regex3 = new RegExp("\\d{3}-\\d{4}");

主要メソッド一覧

メソッド 返り値 用途
regex.test(str) true / false マッチするかどうかの判定
str.match(regex) 配列 / null マッチした文字列の取得
str.matchAll(regex) イテレータ 全マッチのキャプチャグループ含む取得
str.replace(regex, rep) 文字列 マッチ箇所の置換
str.replaceAll(regex, rep) 文字列 全マッチ箇所の置換(gフラグ必須)
str.search(regex) インデックス / -1 最初のマッチ位置の取得
str.split(regex) 配列 パターンで文字列を分割

実務コード例

// 1. バリデーション(test) const isEmail = /^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$/.test(input); if (!isEmail) { showError("メールアドレスの形式が正しくありません"); } // 2. マッチ結果の取得(match) const url = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"; const videoId = url.match(/[?&]v=([a-zA-Z0-9_-]{11})/)?.[1]; // videoId → "dQw4w9WgXcQ" // 3. 全件置換(replace + g フラグ) const cleaned = rawText.replace(/\u3000/g, " "); // 全角スペース→半角 // 4. 分割(split) const items = "apple, banana, cherry ,date".split(/\s*,\s*/); // items → ["apple", "banana", "cherry", "date"] // 5. 全マッチの取得(matchAll) const text = "価格: ¥1,200 と ¥3,500 です"; const prices = [...text.matchAll(/¥([\d,]+)/g)]; // prices[0][1] → "1,200" prices[1][1] → "3,500"

フラグ(修飾子)

フラグ 名称 効果
g global 全マッチを検索(最初の1件で止まらない)
i ignoreCase 大文字・小文字を区別しない
m multiline ^ $ が各行の先頭・末尾にマッチ
s dotAll . が改行文字にもマッチ
u unicode Unicodeコードポイントとして処理(日本語で推奨)

名前付きキャプチャグループ(ES2018+)

ES2018で追加された名前付きキャプチャグループを使うと、キャプチャした値に名前でアクセスできる。$1, $2 のような番号より可読性が高く、パターンが複雑になっても保守しやすい。

// 名前付きキャプチャグループ: (?<名前>パターン) const datePattern = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/; const result = "2026-03-16".match(datePattern); console.log(result.groups.year); // "2026" console.log(result.groups.month); // "03" console.log(result.groups.day); // "16" // 置換での名前付き参照 "2026-03-16".replace(datePattern, "$<year>年$<month>月$<day>日"); // → "2026年03月16日"

Point

名前付きキャプチャグループはIE11では非対応だが、モダンブラウザ(Chrome 64+、Firefox 78+、Safari 11.1+、Edge 79+)では全て対応済み。2026年現在、IE11のサポートが不要なプロジェクトであれば積極的に使おう。

正規表現の落とし穴と注意点

正規表現は強力なツールだが、知らないと予期しない結果になる落とし穴がいくつかある。ここでは実務で特に遭遇しやすい4つの注意点を解説する。

1. 貪欲マッチ vs 非貪欲マッチ(.* vs .*?)

正規表現エンジンはデフォルトで「貪欲(greedy)」に動作し、できるだけ多くの文字にマッチしようとする。HTMLタグの取得で意図しない範囲までマッチしてしまうのはこれが原因だ。

// テスト文字列: "<div>hello</div><div>world</div>" // 貪欲マッチ(.*)→ 最初の <div> から最後の </div> まで全体にマッチ /<div>.*<\/div>/ // マッチ: "<div>hello</div><div>world</div>" // 非貪欲マッチ(.*?)→ 最初の <div> から最も近い </div> まで /<div>.*?<\/div>/ // マッチ: "<div>hello</div>"

対策

.* を使うときは「本当に全部マッチさせたいのか」を常に自問する。特にHTMLタグや引用符で囲まれた文字列を扱う場合は、.*?(非貪欲)か、[^<]*(特定文字以外)を使うほうが安全だ。

2. 日本語(マルチバイト)文字の扱い

JavaScript の正規表現でサロゲートペア(絵文字や一部の漢字)を扱う場合、u フラグを付けないと正しく動作しない。1文字として扱いたいのに2文字として認識されてしまう問題が起きる。

// 絵文字を正しく扱う "".match(/./); // 1文字に見えるが2つにマッチする可能性がある "".match(/./u); // u フラグで正しく1文字としてマッチ // Unicode文字プロパティ(ES2018, u フラグ必須) /\p{Script=Hiragana}/u // ひらがな1文字 /\p{Script=Katakana}/u // カタカナ1文字 /\p{Script=Han}/u // 漢字1文字

3. 改行文字の注意(\n vs \r\n)

改行コードはOS環境によって異なる。macOS/Linux は \n(LF)、Windows は \r\n(CRLF)が標準だ。ユーザーがテキストエリアに入力したデータや、CSVファイルの内容を処理するときにこの違いが問題になることがある。

// 改行コードを統一してから処理する const normalized = text.replace(/\r\n/g, "\n"); // 改行コードに依存しないパターン /\r?\n/g // \n と \r\n の両方にマッチ

4. パフォーマンス(バックトラッキング爆発)

正規表現エンジンはマッチに失敗すると別の経路を試みる「バックトラッキング」を行う。量指定子をネストさせると組み合わせが指数関数的に増大し、処理が極端に遅くなる「バックトラッキング爆発(Catastrophic Backtracking)」が起きる。

// 危険なパターン: 量指定子のネスト /(a+)+/ // "aaaaaaaaaaaX" に対して指数関数的に遅くなる /(a|aa)+/ // あいまいな代替 → 同様に遅くなる // 安全な書き換え /a+/ // シンプルに /a{2,}/ // 具体的な回数指定に

注意: ReDoS攻撃

バックトラッキング爆発はセキュリティ脆弱性にもなる。ユーザー入力を正規表現パターンに直接使う場合、悪意あるユーザーが意図的に処理を遅延させる「ReDoS(Regular Expression Denial of Service)」攻撃の標的になりうる。ユーザー入力をパターンに使う場合は必ずエスケープ処理を行い、タイムアウトを設けること。

Python・PHPでの使い方の違い

正規表現の基本構文は共通だが、各言語でのAPIや記法に差がある。特にPythonの matchsearch の違いは実務でよくハマるポイントなので注意したい。

Python

Pythonでは標準ライブラリの re モジュールを使う。r"pattern"(rawストリング)でバックスラッシュを書きやすくするのが慣例だ。同じパターンを複数回使う場合は re.compile() でコンパイルしておくとパフォーマンスが向上する。

import re # 基本的な使い方 pattern = r"\d{3}-\d{4}" re.match(r"^\d+", "123abc") # 文字列の先頭からマッチ re.search(r"\d+", "abc123") # 文字列全体を検索 re.findall(r"\d+", "a1b2c3") # ['1', '2', '3'] re.sub(r"\d+", "N", "a1b2c3") # 'aNbNcN'(置換) re.split(r"\s+", "hello world") # ['hello', 'world'] # コンパイルしてパフォーマンス改善 regex = re.compile(r"\d{4}-\d{2}-\d{2}") regex.search("Date: 2026-03-16")

PHP

PHPでは PCRE(Perl Compatible Regular Expressions)を使う preg_* 関数群が標準だ。パターンは /pattern/flags 形式でデリミタが必要な点に注意。JavaScriptに慣れた人が最初につまずきやすいポイントだ。

// 基本的な使い方 $pattern = '/\d{3}-\d{4}/'; preg_match('/^\d+/', '123abc', $matches); // マッチして $matches に格納 preg_match_all('/\d+/', 'a1b2c3', $matches);// 全件マッチ preg_replace('/\d+/', 'N', 'a1b2c3'); // 'aNbNcN' preg_split('/\s+/', 'hello world'); // ['hello', 'world']
操作 JavaScript Python PHP
マッチ確認 regex.test(str) re.search(pat, str) preg_match(pat, str)
マッチ結果取得 str.match(regex) re.findall(pat, str) preg_match_all(pat, str)
置換 str.replace(regex, rep) re.sub(pat, rep, str) preg_replace(pat, rep, str)
分割 str.split(regex) re.split(pat, str) preg_split(pat, str)

正規表現テスターの活用

正規表現は書いてすぐ動くとは限らない。「動いているつもりが想定外のパターンにもマッチしていた」という経験をしたことがある人は少なくないはずだ。テスターを使ってパターンとテスト文字列を並べて確認する習慣が、バグを早期に発見する一番の近道になる。

  1. パターンを入力

    正規表現フィールドに試したいパターンを入力する。メタ文字の入力補助機能があるため、初心者でも迷わず使い始められる。

  2. テスト文字列を貼り付け

    マッチ確認したい文字列(メールアドレス一覧、ログデータなど)をテキストエリアに貼り付ける。ローカル処理なので、実際のログデータや個人情報が含まれていても安全だ。

  3. マッチ結果をリアルタイム確認

    マッチした部分がハイライト表示される。キャプチャグループの内容も個別に確認できる。

  4. フラグを切り替えて動作確認

    g(グローバル)、i(大文字小文字無視)、m(複数行)フラグをON/OFFして挙動の違いを把握する。フラグ1つで動作が変わることを体感しておくと、後の理解が速くなる。

ツールで効率化

当サイトの正規表現テスターはブラウザ上で完全動作する。入力したデータがサーバーに送信されないため、ログや個人情報を含むデータでも安心して使える。

パフォーマンスの注意点

正規表現は便利だが、書き方を誤ると極端に遅くなる「バックトラッキング爆発(Catastrophic Backtracking)」という問題が発生する。本番環境でユーザー入力を処理する場合は特に意識が必要だ。

パフォーマンス改善のポイント

正規表現テスターを今すぐ使う

この記事で紹介した20パターンをブラウザ上でリアルタイムに確認できる。入力データはサーバーに送信されないため、ログや個人情報を含むデータも安心してテストできる。

よくある質問

正規表現とは何ですか?
正規表現(Regular Expression)は、文字列の中から特定のパターンに一致する部分を検索・抽出・置換するための記法です。メールアドレスや電話番号のバリデーション、ログからの情報抽出、テキストの一括置換など、プログラミングやテキスト処理のあらゆる場面で使われます。JavaScript・Python・PHPなど、ほぼすべてのプログラミング言語でサポートされています。
正規表現は覚える必要がありますか?
すべてのメタ文字や構文を暗記する必要はありません。この記事のパターン20選のように、よく使うパターンをコピペで使えるようになるだけでも十分実用的です。基本的なメタ文字(. * + ? [] () | ^ $)の意味を理解しておけば、既存のパターンを読み解いたり、少しカスタマイズしたりできるようになります。まずは当サイトの正規表現テスターでパターンを試しながら感覚を掴むのがおすすめです。
JavaScriptとPHPで正規表現は違いますか?
基本的なメタ文字(. * + ? [] () | ^ $)の意味はほぼ同じですが、APIの使い方やフラグの指定方法に違いがあります。JavaScriptでは /pattern/flags のリテラル記法を使い、PHPでは preg_match('/pattern/', $str) のようにデリミタ付きの文字列を使います。また、後読み(lookbehind)のサポート状況やUnicodeの扱いにも差があります。この記事の「Python・PHPでの使い方の違い」セクションで詳しく比較しています。
正規表現はどの言語でも同じですか?
基本的なメタ文字(. * + ? [] () | ^ $)の意味はほぼ共通だが、言語・エンジンによって細かい差がある。後読み(lookbehind)のサポート状況、Unicodeへの対応、特定のエスケープシーケンスの有無などが異なる。JavaScriptとPHPのPCREでは比較的互換性が高いが、Python・Ruby・Javaではそれぞれ独自の仕様があるため、実際に使う言語のドキュメントを確認することを強くすすめる。
正規表現で日本語を扱えますか?
扱えます。ひらがな・カタカナ・漢字はUnicodeのコードポイント範囲で指定できます(例: ひらがなは [\u3041-\u3096])。また、Unicodeカテゴリプロパティに対応したエンジンでは \p{Script=Hiragana} のように書けます。JavaScriptでは ES2018 以降、u フラグを付けることでUnicode文字プロパティが使えます(/\p{sc=Hiragana}/u)。
正規表現のデバッグ方法は?
まず当サイトの正規表現テスターや regex101.com などのオンラインツールを使って、パターンとテスト文字列をリアルタイムで確認するのが手軽だ。それでも解決しない場合は、複雑なパターンを小さな部分に分解して一つずつ確認していく方法が効果的。regex101.com の「debugger」機能はマッチのステップを視覚的に追えるため、どこでつまずいているのかが一目でわかる。
matchsearchの違いは何ですか?
Pythonの re モジュールの話だ。re.match() は文字列の「先頭」からのマッチのみを試みる。一方 re.search() は文字列「全体」を検索し、最初にマッチした位置を返す。例えば re.match(r"\d+", "abc123") はNoneを返すが、re.search(r"\d+", "abc123") は "123" のマッチを返す。先頭からマッチさせたいなら match、文字列中のどこかを探すなら search と使い分けてほしい。
メールアドレスの正規表現を完全にするにはどうすれば?
RFC 5321/5322 で定義されたメールアドレスの仕様は非常に複雑で、完全に正規表現で検証するのは現実的ではない。実務では「@が1つ含まれ、ドメイン部分にドットが含まれる」程度のゆるいバリデーションで十分なケースがほとんどだ。筆者も以前、厳密な正規表現を書いて特殊なメールアドレス(例:プラス記号を含むもの)を弾いてしまい、ユーザーからクレームが来た経験がある。厳密に検証したいなら、確認メールを送る「メール確認フロー」の実装が現実的な解だ。
正規表現でHTMLをパースするのはなぜ良くないの?
HTMLは入れ子構造(ネスト)を持つ文脈自由言語であり、正規表現(有限オートマトン)では完全に表現できない。ネストしたタグの対応関係を正規表現だけで追うことは原理的に不可能だ。実際のHTMLは自己閉じタグ・コメント・CDATA・属性値内の特殊文字など例外だらけで、正規表現で全ケースを捌こうとするとパターンが複雑になりバグが増える一方だ。HTMLの解析にはDOM API・BeautifulSoup(Python)・cheerio(JavaScript)などの専用パーサを使う方が正解だ。