PHPの正規表現の置換方法について

採用はこちら

PHPで文字列を置換する方法はいくつかあります。

固定された文字列を置換するだけなら str_replace() で十分ですが、数字や空白、日付形式など、特定のパターンに一致する文字列を置換したい場合は正規表現が便利です。

PHPで正規表現による置換を行う際は、主に次の2つの関数を使用します。

  • preg_replace()
  • preg_replace_callback()

preg_replace() は、一致した文字列を別の文字列へ置換するときに使います。

preg_replace_callback() は、一致した文字列を計算したり、条件によって加工したりするときに使います。

この記事では、PHPの正規表現置換について、基本的な使い方から日本語処理、キャプチャ、エラー処理、実務での注意点まで詳しく解説します。

目次

preg_replace()の基本的な使い方

preg_replace()の基本構文

PHPで正規表現置換を行う場合は、preg_replace() を使用します。

基本構文は次のとおりです。

$result = preg_replace(
    $pattern,
    $replacement,
    $subject
);

それぞれの引数には、次の値を指定します。

  • $pattern:検索する正規表現
  • $replacement:置換後の文字列
  • $subject:置換対象の文字列

簡単な例を見てみましょう。

$text = '今日は晴れです。';

$result = preg_replace(
    '/晴れ/u',
    '雨',
    $text
);

echo $result;

実行結果は次のとおりです。

今日は雨です。

晴れ に一致した部分が、 に置き換えられています。

正規表現の区切り文字

PHPの正規表現は、一般的に / で囲みます。

'/検索パターン/'

たとえば、PHP という文字列を検索する場合は、次のように書きます。

'/PHP/'

ただし、区切り文字は / 以外でも構いません。

URLのようにスラッシュが多い文字列では、~# を使うと読みやすくなります。

$url = 'https://example.com/path';

$result = preg_replace(
    '~https://example\.com/~',
    'https://sample.jp/',
    $url
);

/ を区切り文字として使う場合は、URL内のスラッシュをエスケープする必要があります。

'/https:\/\/example\.com\//'

区切り文字を ~ に変えると、次のようにすっきり書けます。

'~https://example\.com/~'

数字を正規表現で置換する方法

数字を1文字ずつ置換する

半角数字を1文字ずつ置換する場合は、[0-9] を使用します。

$text = '商品番号は12345です。';

$result = preg_replace(
    '/[0-9]/',
    '*',
    $text
);

echo $result;

実行結果は次のとおりです。

商品番号は*****です。

数字5文字が、それぞれ * に置き換えられています。

連続する数字をまとめて置換する

連続する数字をまとめて置換したい場合は、+ を付けます。

$text = '商品番号は12345です。';

$result = preg_replace(
    '/[0-9]+/',
    'XXXXX',
    $text
);

echo $result;

実行結果は次のとおりです。

商品番号はXXXXXです。

+ は、直前のパターンが1回以上続くことを表します。

[0-9]   数字1文字
[0-9]+  連続する数字

数字以外を削除する

電話番号や金額から数字だけを取り出したい場合は、数字以外の文字を削除します。

$phone = '090-1234-5678';

$result = preg_replace(
    '/[^0-9]/',
    '',
    $phone
);

echo $result;

実行結果は次のとおりです。

09012345678

[^0-9] は、0から9以外の文字を表します。

\D を使っても、一般的な半角数字の処理では同様の結果になります。

$result = preg_replace(
    '/\D/',
    '',
    $phone
);

ただし、「半角数字以外を削除する」という意図を明確にしたい場合は、[^0-9] のほうが分かりやすいでしょう。

空白を正規表現で置換する方法

連続する空白を1つにまとめる

文字列内の連続する空白を1つにまとめる場合は、\s+ を使用します。

$text = "PHP   正規表現\t置換";

$result = preg_replace(
    '/\s+/',
    ' ',
    $text
);

echo $result;

実行結果は次のとおりです。

PHP 正規表現 置換

\s は、次のような空白文字に一致します。

  • 半角スペース
  • タブ
  • 改行
  • その他の空白文字

そのため、改行を残したい場合は注意が必要です。

スペースとタブだけを置換する

改行を残し、半角スペースとタブだけをまとめたい場合は、次のように書きます。

$result = preg_replace(
    '/[ \t]+/',
    ' ',
    $text
);

[ \t] は、半角スペースまたはタブを表します。

前後の空白も削除する

連続する空白をまとめたうえで、文字列の前後にある空白も削除したい場合は、trim() を組み合わせます。

$text = '   PHP    正規表現   置換   ';

$normalized = preg_replace(
    '/[ \t]+/',
    ' ',
    $text
);

if ($normalized === null) {
    throw new RuntimeException(
        '空白の正規化に失敗しました。'
    );
}

$result = trim($normalized);

echo $result;

実行結果は次のとおりです。

PHP 正規表現 置換

キャプチャを使って置換する方法

キャプチャとは

正規表現では、丸括弧 () で囲んだ部分を保存できます。

この仕組みをキャプチャと呼びます。

保存した文字列は、置換後の文字列で再利用できます。

日付形式を変換する

ハイフン区切りの日付を、日本語形式へ変換してみましょう。

$date = '2026-07-11';

$result = preg_replace(
    '/(\d{4})-(\d{2})-(\d{2})/',
    '$1年$2月$3日',
    $date
);

echo $result;

実行結果は次のとおりです。

2026年07月11日

各キャプチャには、次の値が入ります。

$1 = 2026
$2 = 07
$3 = 11

正規表現の各部分は、次の意味になります。

(\d{4})  4桁の数字
(\d{2})  2桁の数字
(\d{2})  2桁の数字

${1}形式を使用する

キャプチャの参照は、${1} の形式でも書けます。

$result = preg_replace(
    '/(\d{4})-(\d{2})-(\d{2})/',
    '${1}年${2}月${3}日',
    $date
);

キャプチャ参照の直後に数字を続ける場合は、${1} の形式を使うと安全です。

'${1}0'

$10 と書くと、次のどちらなのか分かりにくくなるためです。

  • 1番目のキャプチャの後に0を付ける
  • 10番目のキャプチャを参照する

文字列の順番を入れ替える

キャプチャを使うと、文字列の順番を入れ替えることもできます。

$name = 'Yamada Taro';

$result = preg_replace(
    '/([A-Za-z]+)\s+([A-Za-z]+)/',
    '$2 $1',
    $name
);

echo $result;

実行結果は次のとおりです。

Taro Yamada

日本語の姓名でも同じ考え方で処理できます。

$name = '山田 太郎';

$result = preg_replace(
    '/(\S+)\s+(\S+)/u',
    '$2 $1',
    $name
);

echo $result;

実行結果は次のとおりです。

太郎 山田

名前付きキャプチャを使う際の注意点

preg_replace()の置換文字列では名前を直接参照できない

PHPでは、正規表現側で名前付きキャプチャを定義できます。

$pattern = '/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/';

ただし、preg_replace() の置換文字列では、次のような名前付き参照は使用できません。

'${year}年${month}月${day}日'

置換文字列では、番号を使用します。

$date = '2026-07-11';

$result = preg_replace(
    '/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/',
    '${1}年${2}月${3}日',
    $date
);

echo $result;

名前で参照したい場合はpreg_replace_callback()を使う

キャプチャ名をそのまま利用したい場合は、preg_replace_callback() を使用します。

$date = '2026-07-11';

$result = preg_replace_callback(
    '/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/',
    static function (array $matches): string {
        return sprintf(
            '%s年%s月%s日',
            $matches['year'],
            $matches['month'],
            $matches['day']
        );
    },
    $date
);

echo $result;

コールバック内では、次のようにキャプチャ名で値を取得できます。

$matches['year']
$matches['month']
$matches['day']

複雑な正規表現では、番号だけで管理するよりも名前付きキャプチャのほうが読みやすくなります。

preg_replace_callback()の使い方

一致した数字を加工して置換する

一致した文字列をPHPで加工したい場合は、preg_replace_callback() を使用します。

たとえば、文字列内の金額にカンマを付ける場合は、次のように書けます。

$text = '商品Aは1200円、商品Bは3500円です。';

$result = preg_replace_callback(
    '/\d+/',
    static function (array $matches): string {
        return number_format(
            (int) $matches[0]
        );
    },
    $text
);

echo $result;

実行結果は次のとおりです。

商品Aは1,200円、商品Bは3,500円です。

$matches[0] には、正規表現全体に一致した文字列が入ります。

複数のキャプチャを加工する

商品名と価格をそれぞれ加工する例です。

$text = 'apple:100 banana:250';

$result = preg_replace_callback(
    '/([a-z]+):(\d+)/',
    static function (array $matches): string {
        $name = strtoupper($matches[1]);
        $price = number_format(
            (int) $matches[2]
        );

        return "{$name}: {$price}円";
    },
    $text
);

echo $result;

実行結果は次のとおりです。

APPLE: 100円 BANANA: 250円

外側の変数をコールバック内で使う

コールバック関数の外側にある変数を使用する場合は、use を指定します。

$text = '100 200 300';
$taxRate = 1.1;

$result = preg_replace_callback(
    '/\d+/',
    static function (array $matches) use ($taxRate): string {
        $price = (int) $matches[0];

        return (string) round(
            $price * $taxRate
        );
    },
    $text
);

echo $result;

実行結果は次のとおりです。

110 220 330

PHP 7.4以降では、アロー関数でも書けます。

$result = preg_replace_callback(
    '/\d+/',
    fn(array $matches): string =>
        (string) round(
            (int) $matches[0] * $taxRate
        ),
    $text
);

大文字と小文字を区別せずに置換する方法

i修飾子を使用する

通常、正規表現は大文字と小文字を区別します。

$text = 'PHP php Php';

$result = preg_replace(
    '/php/',
    'JavaScript',
    $text
);

echo $result;

実行結果は次のとおりです。

PHP JavaScript Php

すべて置換する場合は、i 修飾子を付けます。

$text = 'PHP php Php';

$result = preg_replace(
    '/php/i',
    'JavaScript',
    $text
);

echo $result;

実行結果は次のとおりです。

JavaScript JavaScript JavaScript

固定文字列を大文字と小文字を区別せずに置換するだけなら、str_ireplace() も使用できます。

$result = str_ireplace(
    'php',
    'JavaScript',
    $text
);

文字列の先頭や末尾だけを置換する方法

先頭だけを置換する

文字列の先頭は ^ で指定します。

$text = 'PHPは便利です。PHPは人気です。';

$result = preg_replace(
    '/^PHP/',
    'Python',
    $text
);

echo $result;

実行結果は次のとおりです。

Pythonは便利です。PHPは人気です。

末尾だけを置換する

文字列の末尾は $ で指定します。

$text = '画像ファイル.jpg';

$result = preg_replace(
    '/\.jpg$/',
    '.webp',
    $text
);

echo $result;

実行結果は次のとおりです。

画像ファイル.webp

. は、正規表現では任意の1文字を意味します。

ピリオドそのものを表す場合は、\. と書きます。

複数行の各行を対象にする

複数行の文字列で、各行の先頭や末尾を判定する場合は m 修飾子を使用します。

$text = <<<TEXT
apple
banana
apple
TEXT;

$result = preg_replace(
    '/^apple$/m',
    'orange',
    $text
);

echo $result;

実行結果は次のとおりです。

orange
banana
orange

m 修飾子を付けない場合、^$ は文字列全体の先頭と末尾を表します。

複数のパターンをまとめて置換する方法

パターンと置換文字列を配列で指定する

preg_replace() の第1引数と第2引数には、配列を指定できます。

$text = 'りんご、バナナ、みかん';

$patterns = [
    '/りんご/u',
    '/バナナ/u',
    '/みかん/u',
];

$replacements = [
    'Apple',
    'Banana',
    'Orange',
];

$result = preg_replace(
    $patterns,
    $replacements,
    $text
);

echo $result;

実行結果は次のとおりです。

Apple、Banana、Orange

配列の同じ位置にあるパターンと置換文字列が対応します。

$patterns[0] → $replacements[0]
$patterns[1] → $replacements[1]
$patterns[2] → $replacements[2]

複数のパターンを同じ文字列へ置換する

すべて同じ文字列に置換する場合は、第2引数に1つの文字列を指定します。

$text = 'りんご、バナナ、みかん';

$result = preg_replace(
    [
        '/りんご/u',
        '/バナナ/u',
        '/みかん/u',
    ],
    '果物',
    $text
);

echo $result;

実行結果は次のとおりです。

果物、果物、果物

複数パターンは順番に処理される

複数のパターンは同時に置換されるわけではありません。

配列に指定した順番で処理されます。

$text = 'abc';

$result = preg_replace(
    [
        '/abc/',
        '/xyz/',
    ],
    [
        'xyz',
        '123',
    ],
    $text
);

echo $result;

実行結果は次のとおりです。

123

処理の流れは次のとおりです。

abc
↓
xyz
↓
123

最初の置換結果が、次のパターンに一致する場合があるため注意しましょう。

置換回数を制限する方法

置換回数の上限を指定する

preg_replace() の第4引数には、置換回数の上限を指定できます。

$text = 'PHP PHP PHP';

$result = preg_replace(
    '/PHP/',
    'JavaScript',
    $text,
    1
);

echo $result;

実行結果は次のとおりです。

JavaScript PHP PHP

1 を指定しているため、最初に一致した部分だけが置換されています。

すべて置換する場合は、-1 を指定します。

$result = preg_replace(
    '/PHP/',
    'JavaScript',
    $text,
    -1
);

第4引数を省略した場合も、すべて置換されます。

置換回数を取得する

第5引数を指定すると、実際に置換された回数を取得できます。

$text = 'PHP PHP PHP';
$count = 0;

$result = preg_replace(
    '/PHP/',
    'JavaScript',
    $text,
    -1,
    $count
);

echo $result;
echo PHP_EOL;
echo '置換回数: ' . $count;

実行結果は次のとおりです。

JavaScript JavaScript JavaScript
置換回数: 3

日本語やUnicodeを扱う際の注意点

日本語にはu修飾子を付ける

日本語を含むUTF-8文字列を扱う場合は、基本的に u 修飾子を付けます。

$text = '今日は良い天気です。';

$result = preg_replace(
    '/天気/u',
    '天候',
    $text
);

echo $result;

u 修飾子を付けることで、文字列がUTF-8として処理されます。

u修飾子だけで完全なUnicode対応にはならない

u 修飾子を付けても、\d\w\b などが自動的にすべてのUnicode文字を対象にするわけではありません。

半角数字だけを対象にする場合は、[0-9] と明示すると分かりやすくなります。

$result = preg_replace(
    '/[0-9]+/',
    '',
    $text
);

Unicode上の十進数字全般を対象にする場合は、\p{Nd} を使用できます。

$result = preg_replace(
    '/\p{Nd}+/u',
    '',
    $text
);

Unicodeプロパティを文字クラスへ反映したい場合は、(*UCP) を指定する方法もあります。

$result = preg_replace(
    '/(*UCP)\d+/u',
    '',
    $text
);

対象が半角数字だけなら、[0-9] のほうが意図が明確です。

全角数字を半角数字へ変換する

全角数字が入力される可能性がある場合は、mb_convert_kana() で半角へ変換してから処理すると便利です。

$text = '価格は12,800円です。';

$normalized = mb_convert_kana(
    $text,
    'n',
    'UTF-8'
);

$result = preg_replace(
    '/[^0-9]/',
    '',
    $normalized
);

echo $result;

実行結果は次のとおりです。

12800

不正なUTF-8に注意する

u 修飾子を使用している場合、対象文字列に不正なUTF-8が含まれていると処理に失敗する可能性があります。

外部ファイルや他システムから受け取った文字列では、文字コードを確認すると安全です。

if (!mb_check_encoding($text, 'UTF-8')) {
    throw new InvalidArgumentException(
        '入力文字列が正しいUTF-8ではありません。'
    );
}

日本語の文字種を指定する方法

ひらがなを置換する

Unicodeプロパティを使うと、ひらがなを指定できます。

$text = 'ひらがな カタカナ 漢字 ABC';

$result = preg_replace(
    '/\p{Hiragana}+/u',
    '[ひらがな]',
    $text
);

echo $result;

カタカナを置換する

$result = preg_replace(
    '/\p{Katakana}+/u',
    '[カタカナ]',
    $text
);

漢字を置換する

$result = preg_replace(
    '/\p{Han}+/u',
    '[漢字]',
    $text
);

Unicodeプロパティを使用する場合は、基本的に u 修飾子を付けましょう。

先読みと後読みを使う方法

直後の文字を条件にする

直後に特定の文字がある場合だけ一致させたいときは、肯定先読みを使用します。

$text = '価格は1200円、在庫は30個です。';

$result = preg_replace(
    '/\d+(?=円)/u',
    '****',
    $text
);

echo $result;

実行結果は次のとおりです。

価格は****円、在庫は30個です。

(?=円) は、「直後に がある」という条件です。

自体は置換対象に含まれません。

直前の文字を条件にする

直前に特定の文字がある場合だけ一致させたいときは、肯定後読みを使用します。

$text = 'ID:12345 CODE:67890';

$result = preg_replace(
    '/(?<=ID:)\d+/',
    'XXXXX',
    $text
);

echo $result;

実行結果は次のとおりです。

ID:XXXXX CODE:67890

(?<=ID:) は、「直前に ID: がある」という条件です。

複雑な後読みには注意する

固定文字列を使った後読みは比較的扱いやすいですが、複雑な可変長条件ではPCRE2のバージョンやパターンによる制約を受けることがあります。

複雑になる場合は、キャプチャや preg_replace_callback() を使う方法も検討しましょう。

単語単位で置換する方法

英単語の境界を指定する

英単語を単語単位で置換する場合は、\b を使用します。

$text = 'cat category wildcat';

$result = preg_replace(
    '/\bcat\b/',
    'dog',
    $text
);

echo $result;

実行結果は次のとおりです。

dog category wildcat

\b を付けない場合は、ほかの単語に含まれる cat も置換されます。

$result = preg_replace(
    '/cat/',
    'dog',
    $text
);

実行結果は次のとおりです。

dog dogegory wilddog

日本語の単語境界には向いていない

\b は、正規表現上の単語構成文字と、それ以外の文字の境界を判定します。

日本語は通常、単語の間にスペースが入らないため、自然な単語境界の判定には向いていません。

日本語の単語を厳密に処理したい場合は、次の方法を検討します。

  • 前後の文字条件を具体的に指定する
  • 対象語を限定する
  • 形態素解析を使用する

貪欲マッチと最短マッチの違い

貪欲マッチ

.* は、可能な限り長い範囲に一致します。

$text = '<b>太字</b><i>斜体</i>';

$result = preg_replace(
    '/<.*>/',
    '',
    $text
);

このパターンでは、最初の < から最後の > まで、一度に一致する可能性があります。

最短マッチ

.*? は、可能な限り短い範囲に一致します。

$result = preg_replace(
    '/<.*?>/',
    '',
    $text
);

違いは次のとおりです。

.*   可能な限り長く一致
.*?  可能な限り短く一致

否定文字クラスを使う

タグ風の文字列を対象にする場合は、次のように書くほうが意図が明確です。

$result = preg_replace(
    '/<[^>]*>/',
    '',
    $text
);

ただし、正規表現だけでHTML全体を正確に解析することはおすすめできません。

HTMLを置換する際の注意点

タグを削除するならstrip_tags()を使う

HTMLタグを単純に削除する場合は、正規表現よりも strip_tags() が適しています。

$html = '<p>こんにちは<strong>世界</strong></p>';

$result = strip_tags($html);

echo $result;

実行結果は次のとおりです。

こんにちは世界

HTML構造を変更するならパーサーを使う

HTMLには、次のような複雑な構造があります。

  • 入れ子になったタグ
  • 属性
  • コメント
  • script要素
  • style要素
  • 壊れたHTML
  • HTMLエンティティ

HTMLを構造として解析したり、要素を変更したりする場合は、DOMDocument などのHTMLパーサーを使用しましょう。

strip_tags()は完全なサニタイズではない

strip_tags() はタグを削除する関数です。

ユーザー入力のHTMLを安全に表示するための完全なサニタイズ機能ではありません。

許可するタグや属性を細かく制御する必要がある場合は、HTMLサニタイザーの利用を検討しましょう。

URLを正規表現で置換する際の注意点

クエリパラメータを置換する

URLの page パラメータを置換する例です。

$url = 'https://example.com/search?page=3&sort=new';

$result = preg_replace(
    '/([?&]page=)\d+/',
    '${1}1',
    $url
);

echo $result;

実行結果は次のとおりです。

https://example.com/search?page=1&sort=new

ただし、この方法では次のようなケースに対応できない可能性があります。

  • page パラメータが存在しない
  • 値が数字ではない
  • 同じパラメータが複数存在する
  • URLエンコードされている
  • フラグメント内に同じ文字列が含まれている

URLは構造を分解して処理する

URLのクエリパラメータを確実に操作する場合は、次の関数を使用します。

  • parse_url()
  • parse_str()
  • http_build_query()
$url = 'https://example.com/search?page=3&sort=new';

$parts = parse_url($url);

parse_str(
    $parts['query'] ?? '',
    $query
);

$query['page'] = 1;

$result =
    $parts['scheme'] . '://' .
    $parts['host'] .
    ($parts['path'] ?? '') .
    '?' .
    http_build_query($query);

echo $result;

ただし、この単純な例では、次の構成要素が欠落する可能性があります。

  • ユーザー名
  • パスワード
  • ポート番号
  • フラグメント

さまざまなURL形式に対応する場合は、すべての構成要素を考慮する必要があります。

メールアドレスをマスキングする方法

正規表現で一部を伏せ字にする

メールアドレスの先頭2文字だけを残す例です。

$email = 'example@gmail.com';

$result = preg_replace(
    '/^(.{2}).*(@.*)$/',
    '$1***$2',
    $email
);

echo $result;

実行結果は次のとおりです。

ex***@gmail.com

ただし、この正規表現は、メールアドレスの形式が正しいかどうかを確認するものではありません。

バリデーションとマスキングを分ける

メールアドレスの妥当性確認と、表示用のマスキングは分けて処理するのが安全です。

function maskEmail(string $email): string
{
    $atPosition = strrpos($email, '@');

    if ($atPosition === false) {
        throw new InvalidArgumentException(
            'メールアドレスの形式が不正です。'
        );
    }

    $localPart = substr(
        $email,
        0,
        $atPosition
    );

    $domain = substr(
        $email,
        $atPosition
    );

    $firstCharacter = mb_substr(
        $localPart,
        0,
        1,
        'UTF-8'
    );

    return $firstCharacter . '***' . $domain;
}

正規表現を使わなくても簡単に処理できる場合は、文字列関数を使う方法も検討しましょう。

電話番号を整形する方法

携帯電話番号にハイフンを付ける

数字だけの携帯電話番号にハイフンを付ける例です。

$phone = '09012345678';

$result = preg_replace(
    '/^(\d{3})(\d{4})(\d{4})$/',
    '$1-$2-$3',
    $phone
);

echo $result;

実行結果は次のとおりです。

090-1234-5678

日本の電話番号は形式が一定ではない

日本の電話番号には、さまざまな形式があります。

03-1234-5678
045-123-4567
0120-123-456
0800-123-4567

すべての電話番号を1つの単純な正規表現で正確に整形するのは困難です。

携帯電話番号だけを対象にする場合は、対象を限定したパターンを使用できます。

$pattern = '/^(070|080|090)(\d{4})(\d{4})$/';

電話番号の種類や桁数を明確にしたうえで、正規表現を設計しましょう。

改行コードを置換する方法

改行コードを統一する

OSや環境によって、改行コードは異なります。

Windows   \r\n
Linux     \n
旧Mac     \r

すべて \n に統一する場合は、次のように書けます。

$text = "1行目\r\n2行目\r3行目\n4行目";

$result = preg_replace(
    '/\r\n?|\n/',
    "\n",
    $text
);

各種改行をまとめて処理する

より幅広い改行シーケンスを対象にする場合は、\R を使用できます。

$result = preg_replace(
    '/\R/u',
    "\n",
    $text
);

\R は、CRLF、CR、LF以外のUnicode改行にも一致します。

連続する改行を減らす

3つ以上連続する改行を2つにまとめる例です。

$text = "段落1\n\n\n\n段落2";

$result = preg_replace(
    '/\n{3,}/',
    "\n\n",
    $text
);

echo $result;

量指定子の意味は次のとおりです。

{3}    ちょうど3回
{3,}   3回以上
{2,5}  2回以上5回以下

ユーザー入力を正規表現に使う際の注意点

入力値をそのままパターンに入れない

ユーザー入力をそのまま正規表現へ組み込むと、特殊文字によってパターンの意味が変わる可能性があります。

$keyword = $_GET['keyword'] ?? '';

$pattern = '/' . $keyword . '/u';

$result = preg_replace(
    $pattern,
    '',
    $text
);

次のような文字が入力されると、意図しない一致や正規表現エラーにつながる可能性があります。

/
*
[
(
.
+
?

preg_quote()でエスケープする

入力値を固定文字列として正規表現に組み込む場合は、preg_quote() を使用します。

$keyword = $_GET['keyword'] ?? '';

$escapedKeyword = preg_quote(
    $keyword,
    '/'
);

$pattern = '/' . $escapedKeyword . '/u';

$result = preg_replace(
    $pattern,
    '',
    $text
);

第2引数には、正規表現の区切り文字を指定します。

preg_quote($keyword, '/');

区切り文字が ~ の場合は、次のようにします。

$escapedKeyword = preg_quote(
    $keyword,
    '~'
);

$pattern = '~' . $escapedKeyword . '~u';

固定文字列ならstr_replace()を使う

ユーザー入力を固定文字列として置換するだけなら、str_replace() のほうが簡単です。

$result = str_replace(
    $keyword,
    '',
    $text
);

preg_quote() は、正規表現上の特殊文字を無効化する関数です。

SQLインジェクション対策やHTMLエスケープとは別の処理なので注意しましょう。

preg_replace()のエラー処理

正規表現エラーではnullが返る

preg_replace() は、正規表現エラーが発生すると null を返します。

$result = preg_replace(
    '/[/',
    'test',
    'example'
);

if ($result === null) {
    echo '正規表現エラーが発生しました。';
}

PHP 8.0以降ではpreg_last_error_msg()を使う

PHP 8.0以降では、preg_last_error_msg() でエラーメッセージを取得できます。

$result = preg_replace(
    '/[/',
    'test',
    'example'
);

if ($result === null) {
    echo preg_last_error_msg();
}

実務では、例外を投げる形にするとエラーを見逃しにくくなります。

$result = preg_replace(
    $pattern,
    $replacement,
    $subject
);

if ($result === null) {
    throw new RuntimeException(
        '正規表現の置換に失敗しました: ' .
        preg_last_error_msg()
    );
}

PHP 7系ではpreg_last_error()を使う

PHP 7系にも対応する場合は、preg_last_error() を使用します。

if ($result === null) {
    throw new RuntimeException(
        '正規表現エラーコード: ' .
        preg_last_error()
    );
}

preg_last_error() はエラーコードを返します。

必要に応じて、エラーコードごとにメッセージを設定しましょう。

nullを空文字へ変換しない

次の書き方は簡単ですが、正規表現エラーを見逃す可能性があります。

$result = preg_replace(
    '/[ \t]+/',
    ' ',
    $text
) ?? '';

preg_replace() がエラーで null を返した場合も、空文字列へ変換されてしまいます。

処理失敗と正常な空文字列を区別したい場合は、明示的に null を確認しましょう。

$result = preg_replace(
    '/[ \t]+/',
    ' ',
    $text
);

if ($result === null) {
    throw new RuntimeException(
        preg_last_error_msg()
    );
}

preg_replace()とstr_replace()の使い分け

固定文字列の置換にはstr_replace()を使う

置換対象が固定された文字列なら、str_replace() を使用します。

$text = 'PHPは便利です。';

$result = str_replace(
    'PHP',
    'JavaScript',
    $text
);

正規表現を使わないため、コードの意図が分かりやすくなります。

パターンによる置換にはpreg_replace()を使う

数字や文字種などのパターンで検索する場合は、preg_replace() を使用します。

$text = '商品123、商品456';

$result = preg_replace(
    '/商品\d+/',
    '商品XXX',
    $text
);

一致内容を加工するならpreg_replace_callback()を使う

一致した数字にカンマを付けたり、計算した結果へ置き換えたりする場合は、preg_replace_callback() を使用します。

用途ごとの使い分けは次のとおりです。

やりたいこと使用する関数
固定文字列を置換するstr_replace()
大文字・小文字を無視して固定文字列を置換するstr_ireplace()
正規表現に一致する文字列を置換するpreg_replace()
一致した内容を加工して置換するpreg_replace_callback()
HTMLタグを単純に削除するstrip_tags()
全角・半角を変換するmb_convert_kana()

正規表現で書ける処理でも、専用関数を使ったほうが簡単で安全な場合があります。

正規表現でよく使う記号

基本的なメタ文字

PHPの正規表現でよく使う記号は次のとおりです。

記号意味
.任意の1文字
\d数字
\D数字以外
\s空白文字
\S空白文字以外
\w単語構成文字
\W単語構成文字以外
^文字列または行の先頭
$文字列または行の末尾
*0回以上
+1回以上
?0回または1回
{n}ちょうどn回
{n,}n回以上
{n,m}n回以上m回以下
[...]文字クラス
[^...]否定文字クラス
(...)キャプチャグループ
(?:...)キャプチャしないグループ
A|BAまたはB
\b単語境界
(?=...)肯定先読み
(?!...)否定先読み
(?<=...)肯定後読み
(?<!...)否定後読み

\d\w\b は、UTFモードやUnicodeプロパティの設定によって判定範囲が変わる場合があります。

対象文字を明確にしたい場合は、[0-9] など具体的な文字クラスを使用しましょう。

正規表現でよく使う修飾子

主な修飾子

PHPの正規表現では、パターンの末尾に修飾子を指定できます。

修飾子意味
i大文字と小文字を区別しない
m複数行モード
s. が改行にも一致する
uUTF-8として処理する
x空白やコメントを使って記述する

s修飾子の使い方

通常、. は改行には一致しません。

s 修飾子を付けると、改行にも一致します。

$text = "開始\n本文\n終了";

$result = preg_replace(
    '/開始.*終了/s',
    '置換済み',
    $text
);

echo $result;

実行結果は次のとおりです。

置換済み

x修飾子の使い方

x 修飾子を使用すると、複雑な正規表現を複数行で書けます。

$date = '2026-07-11';

$pattern = '
/
    (\d{4})  # 年
    -
    (\d{2})  # 月
    -
    (\d{2})  # 日
/x
';

$result = preg_replace(
    $pattern,
    '$1年$2月$3日',
    $date
);

echo $result;

x 修飾子を使うと、パターン内の通常の空白は無視されます。

空白そのものに一致させたい場合は、\s[ ] を使用します。

実務で使いやすい安全なコード例

空白を正規化する関数

実務では、preg_replace() の戻り値を確認して、エラーを明示的に処理すると安全です。

<?php

declare(strict_types=1);

function normalizeWhitespace(string $text): string
{
    $result = preg_replace(
        '/[ \t]+/u',
        ' ',
        $text
    );

    if ($result === null) {
        throw new RuntimeException(
            '正規表現の置換に失敗しました: ' .
            preg_last_error_msg()
        );
    }

    return trim($result);
}

$text = '   PHP    正規表現   置換   ';

echo normalizeWhitespace($text);

実行結果は次のとおりです。

PHP 正規表現 置換

日付形式を変換する関数

<?php

declare(strict_types=1);

function formatJapaneseDate(string $date): string
{
    $result = preg_replace(
        '/^(\d{4})-(\d{2})-(\d{2})$/',
        '${1}年${2}月${3}日',
        $date
    );

    if ($result === null) {
        throw new RuntimeException(
            '正規表現の置換に失敗しました: ' .
            preg_last_error_msg()
        );
    }

    return $result;
}

echo formatJapaneseDate('2026-07-11');

実行結果は次のとおりです。

2026年07月11日

ただし、このコードは文字列の形式を変換しているだけです。

2026-99-99 のような存在しない日付も形式上は一致します。

実際の日付として正しいか確認する場合は、DateTimeImmutable などを使用しましょう。

PHPの正規表現置換で覚えておきたいポイント

PHPで正規表現置換を行うときは、次のポイントを押さえておきましょう。

固定文字列ならstr_replace()を使う

正規表現が必要ない場合は、str_replace() のほうが簡単で読みやすくなります。

パターン置換にはpreg_replace()を使う

数字、空白、文字種、日付形式など、特定のパターンを置換する場合に適しています。

一致内容を加工するならpreg_replace_callback()を使う

計算、条件分岐、文字列加工が必要な場合は、コールバック関数を使用します。

日本語にはu修飾子を付ける

日本語を含むUTF-8文字列を処理する場合は、基本的に u 修飾子を付けます。

名前付きキャプチャはコールバックで利用する

preg_replace() の置換文字列では、$1${1} の番号参照を使用します。

名前付きキャプチャを名前で参照したい場合は、preg_replace_callback() を使います。

正規表現エラーではnullが返る

preg_replace()null を返した場合は、正規表現エラーが発生しています。

PHP 8.0以降では、preg_last_error_msg() でエラー内容を確認できます。

構造化データには専用の処理を使う

HTML、URL、メールアドレス、電話番号などは、正規表現だけでは正確に処理できない場合があります。

専用関数やパーサーがある場合は、そちらを優先しましょう。

まとめ

PHPで正規表現置換を行う場合は、基本的に preg_replace() を使用します。

一致した文字列をそのまま置換するだけなら preg_replace()、一致内容を加工する場合は preg_replace_callback() が適しています。

また、固定文字列を置換するだけなら、正規表現を使わず str_replace() を選ぶほうが簡単です。

正規表現は非常に便利ですが、複雑になりすぎるとコードが読みにくくなります。

次の点を意識すると、安全で保守しやすいコードになります。

  • 正規表現が本当に必要か確認する
  • 日本語には u 修飾子を付ける
  • キャプチャの参照方法を理解する
  • エラー時の null を確認する
  • HTMLやURLには専用の処理を使う

用途に合った関数を選び、正規表現を必要な範囲に限定して使うことが重要です。

以上、PHPの正規表現の置換方法についてでした。

最後までお読みいただき、ありがとうございました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次