正規表現(Regular Expression)は、文字列のパターンを簡潔に表現する記法です。
入力チェック、ログの検索、文字列の置換など、開発のさまざまな場面で使われます。
一方で、書いた本人以外には読みにくい、思わぬ入力で遅くなるなど、扱いに注意が必要な面もあります。
この記事では、基本から実務での注意点までを整理します。
基本のメタ文字
| 記号 | 意味 | 例 |
|---|---|---|
. |
任意の1文字(改行を除く) | a.c は abc、a1c などにマッチ |
^ / $ |
行頭/行末 | ^abc$ は「abc」だけにマッチ |
[ ] |
文字クラス(いずれか1文字) | [a-z] は小文字1文字 |
[^ ] |
否定の文字クラス | [^0-9] は数字以外 |
\| |
または | cat\|dog |
( ) |
グループ化・キャプチャ | (ab)+ |
\d \w \s |
数字/英数字とアンダースコア/空白 | \d{3} |
量指定子
*:0回以上の繰り返し+:1回以上の繰り返し?:0回または1回{n}、{n,m}:n回、またはn回以上m回以下
実用的なパターン例
- 日本の郵便番号:
^\d{3}-\d{4}$ - 年月日(YYYY-MM-DD形式):
^\d{4}-\d{2}-\d{2}$(形式だけを見るもので、13月などの日付の妥当性は判定しません) - 半角英数字のみ、8文字以上:
^[A-Za-z0-9]{8,}$
メールアドレスの完全な検証を正規表現だけで行おうとするのは、現実的ではありません。
形式の簡易チェックにとどめ、実在確認は確認メールの送信で行うのが一般的です。
実務で困りやすいポイント
1. 貪欲マッチ(greedy)と最短一致
量指定子は、既定ではできるだけ長くマッチしようとします。
たとえば <.+> を <b>太字</b> に適用すると、先頭の <b> ではなく、文字列全体にマッチします。
? を付けた <.+?> にすると、最短でマッチします。
2. 特殊文字のエスケープ
. * + ? ( ) [ ] などを文字として扱いたいときは、\. のようにバックスラッシュでエスケープします。
プログラミング言語の文字列リテラルでは、バックスラッシュ自体のエスケープも必要になるため、Pythonのraw文字列(r"\d+")のような書き方が便利です。
3. 言語・ライブラリによる方言の違い
先読み・後読み、名前付きグループ、Unicodeの扱いなどは、言語や処理系によって対応状況や書き方が異なります。
別の環境へ持ち込むときは、動作を再確認してください。
4. 日本語を扱うときの注意
全角と半角、ひらがなとカタカナ、濁点の結合文字など、見た目が同じでも別の文字として扱われるものがあります。
文字範囲を指定するときは、Unicodeの範囲(例:ひらがなは ぁ-ゖ)を確認しましょう。
5. 性能問題(ReDoS)
(a+)+$ のように、入れ子になった繰り返しを含むパターンは、特定の入力に対して処理時間が急激に増えることがあります。
これを悪用して、サーバーを過負荷にする攻撃をReDoSと呼びます。
ユーザー入力に正規表現を適用する場合は、入力長の上限を設ける、入れ子の繰り返しを避ける、実行時間の制限を設けるといった対策を行ってください。
読みやすく保つコツ
- 複雑なパターンは、小さな部品に分けて、名前を付けた変数で組み立てる。
- 対応している言語では、コメント付きのverboseモードを使う。
- 正規表現を使わなくても書ける処理は、文字列メソッドで書く。
- 典型的な入力と、境界値・異常値の両方でテストを書く。
まとめ
正規表現は強力ですが、万能ではありません。
基本のメタ文字と量指定子を押さえたうえで、貪欲マッチ、エスケープ、性能問題といった落とし穴に気を付ければ、実務で安心して使えます。
書いたパターンは、いくつかの入力を試せるテスターで動作を確認してから組み込みましょう。