正規表現
文字列のパターンを表す記法
文字列の検索・抽出・置換・形式チェックに利用される
### 使用上の注意点
| 注意点 | 内容 | 対策 |
|---|---|---|
| アンカーの付け忘れ | `\d{3}` だけでは `abc123xyz` にもマッチする | 全体一致にしたい場合は `^` `$` を付ける |
| `$` と末尾の改行 | Python などでは `$` が末尾の改行の直前にもマッチする | `fullmatch` や `\Z` を使う |
| ReDoS | `^(a+)+$` のように入れ子の量指定子があると、特定の入力で計算量が爆発する | 入れ子の量指定子を避ける、入力長を制限する、タイムアウト付きエンジンを使う |
| 全角・半角 | `\d` が全角数字を含むかは言語依存 | `[0-9]` を明示する、事前に正規化する |
| HTML のパース | 正規表現では入れ子構造を正しく扱えない | HTML パーサや DOMPurify などを使う |
| 可読性 | 長い正規表現は保守が困難 | 名前付きグループ、`x` フラグ、部品への分割で読みやすくする |
```bash / [ 検索対象文字列 ] / [ フラグ ] ┗ 正規表現開始 ┗ 検索対象文字列終了 ```
### 検索対象文字列
#### メタ文字 | 記法 | 意味 | 例 | マッチする例 | |---|---|---|---| | `.` | 改行以外の任意の1文字 | `a.c` | `abc`, `a1c` | | `^` | 文字列(`m` フラグ時は行)の先頭 | `^abc` | `abc` で始まる文字列 | | `$` | 文字列(`m` フラグ時は行)の末尾 | `abc$` | `abc` で終わる文字列 | | `\d` | 数字(`[0-9]`) | `\d\d` | `12` | | `\w` | 英数字とアンダースコア(`[A-Za-z0-9_]`) | `\w+` | `user_1` | | `\s` | 空白文字(スペース、タブ、改行など) | `a\sb` | `a b` | | `\D` `\W` `\S` | `\d` `\w` `\s` の否定 | `\D+` | `abc` | | `\b` | 単語の境界 | `\bcat\b` | `cat`(`concat` にはマッチしない) | | `\|` | OR(いずれか) | `cat\|dog` | `cat`, `dog` | | `\` | 直後のメタ文字をエスケープ | `\.` | `.`(ドットそのもの) |
##### リテラル文字列として扱う場合、エスケープが必要な文字 ```text . ^ $ * + ? ( ) [ ] { } \ | ```
#### 量指定子 | 記法 | 意味 | 例 | マッチする例 | |---|---|---|---| | `*` | 直前を0回以上繰り返す | `ab*` | `a`, `abbb` | | `+` | 直前を1回以上繰り返す | `ab+` | `ab`, `abbb` | | `?` | 直前が0回または1回 | `colou?r` | `color`, `colour` | | `{n}` | ちょうどn回 | `\d{4}` | `2026` | | `{n,}` | n回以上 | `\d{3,}` | `123`, `12345` | | `{n,m}` | n回以上m回以下 | `\d{2,4}` | `12`, `1234` | | `*?` `+?` `??` | 最短一致(遅延評価)。デフォルトは最長一致 | `<.+?>` | `<b>` (`<b>text</b>` の最初のタグだけ) |
#### 文字クラス | 記法 | 意味 | 例 | マッチする例 | |---|---|---|---| | `[abc]` | `a` `b` `c` のいずれか1文字 | `[aeiou]` | `e` | | `[^abc]` | `a` `b` `c` **以外** の1文字 | `[^0-9]` | `x` | | `[a-z]` | 範囲指定 | `[A-Za-z]` | `Q` | | `[ぁ-ん]` | ひらがなの範囲 | `[ぁ-ん]+` | `ひらがな` | | `[\s\S]` | 改行を含む任意の1文字 | `[\s\S]*` | 複数行の文字列全体 |
##### `[]` の中での注意 - - `^` (先頭) - `-` (中間) - `]` - `\` は特別な意味を持つ - - `.` - `*` - `+` などはメタ文字ではなくなり、エスケープ不要
#### グループ・先読み・後読み | 記法 | 意味 | 例 | |---|---|---| | `(...)` | キャプチャグループ(部分一致を取り出せる) | `(\d{4})-(\d{2})` | | `(?:...)` | 非キャプチャグループ(まとめるだけ) | `(?:ab)+` | | (?<name>...) | 名前付きグループ(JavaScript / Java / .NET など)
Python : (?P<name>...) | (?<year>\d{4}) | | `\1` | 1番目のキャプチャグループと同じ文字列 | `(\w)\1` は `aa` にマッチ | | `(?=...)` | 肯定先読み(直後が `...` であること) | `\d+(?=円)` | | `(?!...)` | 否定先読み(直後が `...` でないこと) | `\d+(?!円)` | | (?<=...) | 肯定後読み(直前が `...` であること) | (?<=¥)\d+ | | (?<!...) | 否定後読み(直前が `...` でないこと) | (?<!¥)\d+ |
### フラグ | フラグ | 意味 | 対応 | |---|---|---| | `i` | 大文字小文字を区別しない | ほぼ全言語 | | `m` | `^` `$` を各行の先頭・末尾にマッチさせる | ほぼ全言語 | | `s` | `.` が改行にもマッチする(dotall) | JavaScript / Python など | | `g` | すべてのマッチを対象にする | JavaScript | | `x` | 空白とコメントを許可する(読みやすく書ける) | Python / Perl など | | `u` | Unicode として扱う | JavaScript |
```bash / [ 検索対象文字列 ] / [ フラグ ] ┗ 正規表現開始 ┗ 検索対象文字列終了 ```
### 検索対象文字列
#### メタ文字 | 記法 | 意味 | 例 | マッチする例 | |---|---|---|---| | `.` | 改行以外の任意の1文字 | `a.c` | `abc`, `a1c` | | `^` | 文字列(`m` フラグ時は行)の先頭 | `^abc` | `abc` で始まる文字列 | | `$` | 文字列(`m` フラグ時は行)の末尾 | `abc$` | `abc` で終わる文字列 | | `\d` | 数字(`[0-9]`) | `\d\d` | `12` | | `\w` | 英数字とアンダースコア(`[A-Za-z0-9_]`) | `\w+` | `user_1` | | `\s` | 空白文字(スペース、タブ、改行など) | `a\sb` | `a b` | | `\D` `\W` `\S` | `\d` `\w` `\s` の否定 | `\D+` | `abc` | | `\b` | 単語の境界 | `\bcat\b` | `cat`(`concat` にはマッチしない) | | `\|` | OR(いずれか) | `cat\|dog` | `cat`, `dog` | | `\` | 直後のメタ文字をエスケープ | `\.` | `.`(ドットそのもの) |
##### リテラル文字列として扱う場合、エスケープが必要な文字 ```text . ^ $ * + ? ( ) [ ] { } \ | ```
#### 量指定子 | 記法 | 意味 | 例 | マッチする例 | |---|---|---|---| | `*` | 直前を0回以上繰り返す | `ab*` | `a`, `abbb` | | `+` | 直前を1回以上繰り返す | `ab+` | `ab`, `abbb` | | `?` | 直前が0回または1回 | `colou?r` | `color`, `colour` | | `{n}` | ちょうどn回 | `\d{4}` | `2026` | | `{n,}` | n回以上 | `\d{3,}` | `123`, `12345` | | `{n,m}` | n回以上m回以下 | `\d{2,4}` | `12`, `1234` | | `*?` `+?` `??` | 最短一致(遅延評価)。デフォルトは最長一致 | `<.+?>` | `<b>` (`<b>text</b>` の最初のタグだけ) |
#### 文字クラス | 記法 | 意味 | 例 | マッチする例 | |---|---|---|---| | `[abc]` | `a` `b` `c` のいずれか1文字 | `[aeiou]` | `e` | | `[^abc]` | `a` `b` `c` **以外** の1文字 | `[^0-9]` | `x` | | `[a-z]` | 範囲指定 | `[A-Za-z]` | `Q` | | `[ぁ-ん]` | ひらがなの範囲 | `[ぁ-ん]+` | `ひらがな` | | `[\s\S]` | 改行を含む任意の1文字 | `[\s\S]*` | 複数行の文字列全体 |
##### `[]` の中での注意 - - `^` (先頭) - `-` (中間) - `]` - `\` は特別な意味を持つ - - `.` - `*` - `+` などはメタ文字ではなくなり、エスケープ不要
#### グループ・先読み・後読み | 記法 | 意味 | 例 | |---|---|---| | `(...)` | キャプチャグループ(部分一致を取り出せる) | `(\d{4})-(\d{2})` | | `(?:...)` | 非キャプチャグループ(まとめるだけ) | `(?:ab)+` | | (?<name>...) | 名前付きグループ(JavaScript / Java / .NET など)
Python : (?P<name>...) | (?<year>\d{4}) | | `\1` | 1番目のキャプチャグループと同じ文字列 | `(\w)\1` は `aa` にマッチ | | `(?=...)` | 肯定先読み(直後が `...` であること) | `\d+(?=円)` | | `(?!...)` | 否定先読み(直後が `...` でないこと) | `\d+(?!円)` | | (?<=...) | 肯定後読み(直前が `...` であること) | (?<=¥)\d+ | | (?<!...) | 否定後読み(直前が `...` でないこと) | (?<!¥)\d+ |
### フラグ | フラグ | 意味 | 対応 | |---|---|---| | `i` | 大文字小文字を区別しない | ほぼ全言語 | | `m` | `^` `$` を各行の先頭・末尾にマッチさせる | ほぼ全言語 | | `s` | `.` が改行にもマッチする(dotall) | JavaScript / Python など | | `g` | すべてのマッチを対象にする | JavaScript | | `x` | 空白とコメントを許可する(読みやすく書ける) | Python / Perl など | | `u` | Unicode として扱う | JavaScript |
バリデーション
入力が期待通りか 検証 すること
正規表現や型・範囲・長さチェックを使い、不正な入力を 受け付けない ようにする
| 原則 | 内容 |
|---|---|
| ホワイトリスト方式 | 「許可するもの」を定義し、それ以外を拒否する(ブラックリストより安全) |
| 信頼できない入力はすべて検証 | フォーム、クエリ、ヘッダ、Cookie、ファイル、外部 API の応答など |
| 早期に検証する | 入力を受けた直後に検証し、不正なら処理を進めない |
| 正規化してから検証する | 前後の空白除去、全角→半角、Unicode 正規化を先に行う |
| 構文と意味を区別する | 形式が正しくても意味的に正しいとは限らない(`2026-02-30` など) |
| エラー情報を出しすぎない | 内部構造や詳細な失敗理由の露出を避ける(認証まわりは特に) |
| ユーザーに分かりやすく伝える | どの項目がなぜ誤りかを具体的に示す |
| 種類 | 検証内容 | 例 | |---|---|---| | 必須チェック | 値が存在し、空でない | 氏名が空でない | | 型チェック | 数値・日付など期待する型である | 年齢が整数 | | 形式チェック | 決められた書式である | 郵便番号、メールアドレス(正規表現を使う) | | 範囲チェック | 最小値・最大値の範囲内である | 年齢が `0`〜`150` | | 長さチェック | 文字数・バイト数の制限内である | ユーザー名が3〜20文字 | | 許可リストチェック | 定められた選択肢のいずれかである | 都道府県コードが `01`〜`47` | | 整合性チェック(相関) | 複数項目の関係が正しい | 開始日 ≦ 終了日、パスワードと確認用が一致 | | 業務ルールチェック | 業務上の制約を満たす | 在庫数以下の注文数、重複登録でない |
| 種類 | 検証内容 | 例 | |---|---|---| | 必須チェック | 値が存在し、空でない | 氏名が空でない | | 型チェック | 数値・日付など期待する型である | 年齢が整数 | | 形式チェック | 決められた書式である | 郵便番号、メールアドレス(正規表現を使う) | | 範囲チェック | 最小値・最大値の範囲内である | 年齢が `0`〜`150` | | 長さチェック | 文字数・バイト数の制限内である | ユーザー名が3〜20文字 | | 許可リストチェック | 定められた選択肢のいずれかである | 都道府県コードが `01`〜`47` | | 整合性チェック(相関) | 複数項目の関係が正しい | 開始日 ≦ 終了日、パスワードと確認用が一致 | | 業務ルールチェック | 業務上の制約を満たす | 在庫数以下の注文数、重複登録でない |
サニタイズ
危険な文字を 無害化 すること : Sanitize(消毒する)
入力値に含まれる 危険な文字や文字列を、無害な形に変換・除去する 処理
正規表現やエスケープ・除去・置換・プレースホルダを使い、入力値が攻撃に悪用されるのを防ぐ(加工して受け入れる)
| 手法 | 内容 | 例 |
|---|---|---|
| エスケープ | 特殊文字を無害な表現に置き換える | < → `<` |
| 除去 | 危険な文字や要素を取り除く | <script> タグの削除 |
| 置換 | 別の文字列に差し替える | 制御文字を空文字に置換 |
| 正規化 | 表記を統一する | 全角英数を半角へ、Unicode 正規化(NFC / NFKC) |
| プレースホルダ | 値をコードと分離して渡す | SQL のバインド変数 |