2026年版 ToolShare Lab / Guide

正規表現入門|よく使うパターンと
実践例まとめ

「メールアドレスの検証をしたい」「ログから特定のパターンを抽出したい」そんな場面で必ず登場する正規表現。難しそうに見えるが、基本ルールさえ覚えれば開発・テスト・データ整形の効率が劇的に上がる。メタ文字の意味から実践的なパターン10選、JavaScript・Python・PHPでの利用方法の違いまで、この1本でまとめた。

読了時間: 約12分 更新日: 2026年3月10日

正規表現とは

正規表現(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-10"; const match = date.match(/(\d{4})-(\d{2})-(\d{2})/); // match[1] → "2026"(年) // match[2] → "03"(月) // match[3] → "10"(日) // 置換での参照($1, $2 でグループを参照) "2026-03-10".replace(/(\d{4})-(\d{2})-(\d{2})/, "$1年$2月$3日") // → "2026年03月10日"

非キャプチャグループ

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

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

先読み・後読み

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

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

よく使う正規表現パターン10選

実務でよく登場するパターンをまとめた。そのままコピーして使いながら、構造を少しずつ読み解いていくと身につきやすい。なお、メールアドレスのパターンについては後述のFAQに補足があるので合わせて確認してほしい。

1. メールアドレス

/^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$/ // 例: user@example.com ✓ / user@.com ✗

2. 日本の電話番号(ハイフンあり)

/^0\d{1,4}-\d{1,4}-\d{4}$/ // 例: 03-1234-5678 ✓ / 090-1234-5678 ✓

3. 日本の郵便番号

/^\d{3}-?\d{4}$/ // 例: 100-0001 ✓ / 1000001 ✓(ハイフンは省略可)

4. URLの検出

/https?:\/\/[a-zA-Z0-9.\-_~:/?#\[\]@!$&'()*+,;=%]+/ // 例: https://example.com/path?q=1 ✓

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

/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/ // 例: 2026-03-10 ✓ / 2026-13-01 ✗

6. IPアドレス(IPv4)

/^(25[0-5]|2[0-4]\d|[01]?\d\d?)(\.(25[0-5]|2[0-4]\d|[01]?\d\d?)){3}$/ // 例: 192.168.1.1 ✓ / 256.0.0.1 ✗

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

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

8. クレジットカード番号(Visa / Mastercard / 16桁)

/^\d{4}[\s\-]?\d{4}[\s\-]?\d{4}[\s\-]?\d{4}$/ // 例: 1234-5678-9012-3456 ✓ / 1234 5678 9012 3456 ✓

9. HTMLタグの除去

/<[^>]*>/g // "<p>Hello <b>World</b></p>".replace(/<[^>]*>/g, "") // → "Hello World"

10. 日本語文字(ひらがな・カタカナ・漢字)

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

JavaScript・Python・PHPでの使い方の違い

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

JavaScript

JavaScriptでは /pattern/flags のリテラル記法が基本だ。String メソッドと RegExp オブジェクトの両方から使える。動的にパターンを生成したい場合はコンストラクタ記法を選ぶ。

// リテラル記法 const regex = /\d{3}-\d{4}/; // コンストラクタ記法(動的パターン生成に使う) const regex2 = new RegExp("\\d{3}-\\d{4}"); // 主要メソッド "090-1234".match(/\d{3}-\d{4}/); // マッチ結果を返す "text".replace(/e/, "E"); // 置換(最初の1件) "text".replace(/e/g, "E"); // 全件置換(g フラグ) /\d+/.test("abc123"); // true/false を返す "a,b,c".split(/,/); // ["a", "b", "c"] // 主要フラグ // g: グローバル(全件マッチ) // i: 大文字小文字を区別しない // m: 複数行モード(^ $ が各行に対応) // s: . が改行にもマッチ(dotAll)

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-10")

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)」という問題が発生する。本番環境でユーザー入力を処理する場合は特に意識が必要だ。

バックトラッキング爆発とは

正規表現エンジンは、マッチに失敗すると別の経路を試みる「バックトラッキング」を行う。これが指数関数的に増大すると処理時間が膨大になる。たった数十文字の入力に対して数秒かかるといった事態が実際に起きる。

// 危険なパターン(ネストした量指定子) /(a+)+/ // "aaaaaaaaaaaaaaaaaX" に対して指数関数的にバックトラック // 安全な書き換え /a+/ // シンプルにする

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

注意: ReDoS攻撃

バックトラッキング爆発はセキュリティ上の脆弱性にもなる。ユーザー入力をそのまま正規表現パターンに使う場合(動的生成)は特に危険で、悪意あるユーザーが意図的に処理時間を膨大にさせる「ReDoS(Regular Expression Denial of Service)」攻撃の標的になりうる。

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

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

よくある質問

正規表現はどの言語でも同じですか?
基本的なメタ文字(. * + ? [] () | ^ $)の意味はほぼ共通だが、言語・エンジンによって細かい差がある。後読み(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)などの専用パーサを使う方が正解だ。