PHPのpreg_replace関数 — 正規表現でパターン置換する使い方と実例

基本文法・構文ガイド

構文:preg_replace(string|array $pattern, string|array $replacement, string|array $subject, int $limit = -1, int &$count = null): string|array|null

// 基本例
preg_replace('/\d/', '#', 'abc123');              // "abc###"
preg_replace('/[aeiou]/i', '*', 'Hello World');    // "H*ll* W*rld"
preg_replace('/(\d{4})-(\d{2})-(\d{2})/', '$3/$2/$1', '2026-08-01'); // "01/08/2026"

PHPのpreg_replace()関数は、正規表現パターンにマッチした文字列を別の文字列に置き換えるための組み込み関数です。str_replace()が固定文字列しか検索できないのに対し、preg_replace()は「数字の連続」「空白の連続」「日付の並び替え」のような可変長・条件付きのパターンを置換できます。一方で、配列パターンの適用順序後方参照の書き方、PHP 7以降で廃止されたe修飾子など、つまずきやすいポイントも多い関数です。この記事では基本構文から後方参照を使った実践例、よくある落とし穴、preg_replace_callback()との使い分けまで解説します。

preg_replace関数とは?

PHPのpreg_replace()は、正規表現パターン(PCRE)で対象の文字列を検索し、マッチした部分を置換文字列に差し替えて返す組み込み関数です。

preg_replace(string|array $pattern, string|array $replacement, string|array $subject, int $limit = -1, int &$count = null): string|array|null

引数の詳細

引数 必須 説明
$pattern string|array 必須 正規表現パターン。デリミタ(通常は/ /)で囲む。配列を渡すと複数パターンをまとめて処理できる
$replacement string|array 必須 置換後の文字列。後方参照($1${1})でキャプチャ内容を埋め込める
$subject string|array 必須 検索・置換対象の文字列。配列を渡すと各要素を置換し、配列で返す
$limit int 任意 各パターンで置換する最大回数。既定値-1は無制限
$count int(参照渡し) 任意 実際に置換された合計回数が代入される変数

⚠️ パターンが不正、または内部でエラーが発生した場合、preg_replace()nullを返します。マッチしなかった場合は元の$subjectがそのまま返るため、戻り値がnullかどうかで区別してください。

基本的な使い方

// 数字だけを取り除く
echo preg_replace('/\d/', '', 'abc123'); // "abc"

// 電話番号からハイフン以外の記号もまとめて除去
echo preg_replace('/\D/', '', '090-1234-5678'); // "09012345678"

// 大文字小文字を区別しない置換(iモディファイア)
echo preg_replace('/hello/i', 'Hi', 'Hello World, hello PHP');
// "Hi World, Hi PHP"

連続する空白・改行をまとめる

$text = "foo   bar\n\n\nbaz";

echo preg_replace('/\s+/', ' ', $text);
// "foo bar baz"

連続するハイフンを1つに潰す

str_replace()では4連続以上のハイフンを1回の呼び出しで完全には潰せませんが、preg_replace()なら量指定子+で一度に処理できます。

$str = "-aaa----b-c-----d--e---f";

echo preg_replace('/-+/', '-', $str);
// "-aaa-b-c-d-e-f"

後方参照(キャプチャグループ)を使った置換

$pattern内の丸括弧()で囲んだ部分はキャプチャグループとなり、$replacement側で$1${1}として参照できます。番号は左括弧の登場順に1から振られます。

// 日付を yyyy-mm-dd から dd/mm/yyyy に並び替える
$date = '2026-08-01';

echo preg_replace('/(\d{4})-(\d{2})-(\d{2})/', '$3/$2/$1', $date);
// "01/08/2026"

改行を<br>タグに変換する

$text = "1行目\n2行目\n3行目";

echo preg_replace('/\n/', '<br>', $text);
// "1行目<br>2行目<br>3行目"

URLを<a>タグでリンク化する

$text = '公式サイトは https://laravelwren.com/ です。';

$linked = preg_replace(
    '#(https?://[\w./%-]+)#',
    '<a href="$1">$1</a>',
    $text
);
echo $linked;
// '公式サイトは <a href="https://laravelwren.com/">https://laravelwren.com/</a> です。'

⚠️ 後方参照の直後に数字が続くと、$1なのか$11なのか曖昧になります。この場合は${1}のように波括弧で囲んで書きます。

$str = preg_replace('/(\w+) (\d+), (\d+)/i', '${1}1,$3', 'April 15, 2003');
echo $str; // "April1,2003"

配列を使った複数パターンの一括置換

$pattern$replacement$subjectはいずれも配列を渡すことができます。

複数パターンをそれぞれ別の文字列に置換する

$patterns     = ['/quick/', '/brown/', '/fox/'];
$replacements = ['slow', 'black', 'bear'];
$string       = 'The quick brown fox jumps over the lazy dog.';

echo preg_replace($patterns, $replacements, $string);
// "The slow black bear jumps over the lazy dog."

$subjectに配列を渡す

$texts = ['foo123', 'bar456'];

print_r(preg_replace('/\d+/', '', $texts));
// ["foo", "bar"]

⚠️ $patternを配列で渡す場合、各パターンは前の置換結果に対して順番に適用されます。以下の例ではabcdと連鎖してしまい、期待した結果になりません。

$p = ['/a/', '/b/', '/c/'];
$r = ['b', 'c', 'd'];

echo preg_replace($p, $r, 'a');
// 期待値: "b"
// 実際の結果: "d"(a→b→c→dと連鎖する)

値の入れ替えなど連鎖を避けたい場合は、一度使わない記号などのプレースホルダーを経由させます。

// aとbを入れ替える
$p = ['/a/', '/b/', '/§/'];
$r = ['§', 'a', 'b'];

echo preg_replace($p, $r, 'ab'); // "ba"

limit・count引数の使い方

// limit: 最初の1件だけ置換する
echo preg_replace('/o/', '0', 'foo bar foo', 1);
// "f0o bar foo"

// count: 置換された合計回数を取得する
$count = 0;
preg_replace(['/\d/', '/\s/'], '*', 'xp 4 to', -1, $count);
echo $count; // 3

preg_replace_callback()が必要なケース

置換内容を単純な文字列で表現できない場合は、コールバック関数でマッチ結果を受け取れるpreg_replace_callback()を使います。

マッチした数値を2倍にする

$result = preg_replace_callback('/\d+/', function ($matches) {
    return $matches[0] * 2;
}, '1回目は3個、2回目は5個');

echo $result; // "1回目は6個、2回目は10個"

名前付きキャプチャグループを使いたい場合

preg_replace()$replacementでは名前付きキャプチャグループ((?<name>...))を参照できません。名前付きグループの値を使いたい場合はpreg_replace_callback()を使います。

// NG: preg_replaceでは名前付きグループを置換文字列で使えない
echo preg_replace('/(?<digits>\d+)/', '[$digits]', '123');
// "[$digits]"(置換されない)

// OK: preg_replace_callbackなら参照できる
echo preg_replace_callback('/(?<digits>\d+)/', function ($m) {
    return '[' . $m['digits'] . ']';
}, '123');
// "[123]"

よくある落とし穴・注意点

eモディファイアはPHP 7で廃止済み

かつてはeモディファイアを付けると$replacementをPHPコードとしてeval()実行できましたが、任意コード実行につながる危険な機能だったためPHP 5.5.0で非推奨化、PHP 7.0.0で完全に削除されました。同等の処理はpreg_replace_callback()で書き直してください。

// PHP 7以降はエラーになる書き方(使用不可)
// preg_replace('/(\d+)/e', 'strtoupper("$1")', $str);

// 代替:preg_replace_callback()を使う
echo preg_replace_callback('/(\d+)/', function ($m) {
    return $m[1] * 2;
}, '値は5です');
// "値は10です"

/u修飾子と不正なUTF-8

日本語などマルチバイト文字を扱う場合はu修飾子(/u)を付けます。ただし$subjectに不正なUTF-8バイト列が含まれていると、preg_replace()は空文字列やnullを返すことがあります。外部入力を扱う場合は、事前にmb_check_encoding()などで文字コードを検証してください。

// 日本語を含むパターンにはuモディファイアを付ける
echo preg_replace('/[ぁ-ん]+/u', '', 'これはtestです');
// "testです"

PHP 8.1以降はnullを渡すと非推奨警告が出る

PHP 8.1以降、$subjectなどの非nullableな引数にnullを渡すとDeprecated警告が発生します。値がnullになり得る変数を渡す前に、明示的に文字列へキャストしてください。

// PHP 8.1+ で $value が null だと Deprecated 警告
preg_replace('/a/', 'b', $value);

// 対策:明示的に文字列へキャストする
preg_replace('/a/', 'b', (string) $value);

preg_replace() / preg_replace_callback() / str_replace() / preg_match() の使い分け

関数 用途 使うべき場面
preg_replace() 正規表現パターンでの検索・置換 可変長・条件付きのパターンを置換したいとき
preg_replace_callback() マッチ結果をコールバックで加工して置換 置換内容を計算・整形したい、名前付きキャプチャを使いたいとき
str_replace() 固定文字列の検索・置換 置換対象が固定の単語・記号で、正規表現が不要なとき
preg_match() 正規表現パターンでのマッチ判定・抽出 置換ではなく、パターンに一致するか調べたい・部分文字列を取り出したいとき

関連記事

FAQ

preg_replaceとstr_replaceの違いは?

str_replace()は固定の文字列をそのまま検索して置換します。preg_replace()は正規表現パターンで検索するため、「数字の連続」「空白の連続」のような可変長・条件付きのパターンも置換できます。置換対象が固定文字列なら処理が軽いstr_replace()で十分です。

// 固定文字列の置換
echo str_replace('-', '', '090-1234-5678'); // "09012345678"

// 正規表現での置換(数字以外をすべて除去)
echo preg_replace('/\D/', '', '090-1234-5678'); // "09012345678"

preg_replaceで大文字・小文字を区別しないようにするには?

パターンの末尾にiモディファイアを付けます。

echo preg_replace('/php/i', 'Laravel', 'I love PHP and php!');
// "I love Laravel and Laravel!"

マッチした文字列を置換文字列に埋め込むには?

パターン内の丸括弧でキャプチャグループを作り、置換側で$1${1}として参照します。後方参照の直後に数字が続く場合は${1}形式を使ってください。

echo preg_replace('/(\d{4})-(\d{2})-(\d{2})/', '$3/$2/$1', '2026-08-01');
// "01/08/2026"

置換した回数を取得するには?

第5引数に変数を渡すと、置換された合計回数が代入されます。

preg_replace('/\d/', '', 'abc123', -1, $count);
echo $count; // 3

置換内容を計算式や関数の結果にしたい場合は?

PHP 7で廃止されたeモディファイアの代わりにpreg_replace_callback()を使います。

echo preg_replace_callback('/\d+/', fn($m) => $m[0] * 2, '値は5です');
// "値は10です"

まとめ

preg_replace()関数のポイントをまとめます。

  • preg_replace($pattern, $replacement, $subject)で正規表現パターンに一致した文字列を置換する
  • 丸括弧でキャプチャグループを作り、$1${1}で置換文字列に埋め込める(後方参照直後に数字が続く場合は${1}を使う)
  • 配列で複数パターンを渡す場合、前の結果に対して順番に適用されるため連鎖置換に注意する
  • eモディファイアはPHP 7で削除済み。置換内容を加工したい場合はpreg_replace_callback()を使う
  • 名前付きキャプチャグループはpreg_replace()の置換文字列では参照できない(preg_replace_callback()で対応)
  • 固定文字列の置換ならstr_replace()の方が処理が軽く、パターンマッチの判定だけならpreg_match()が適している

可変長・条件付きのパターンを置換したいときはpreg_replace()が最も柔軟です。まずは基本の1パターン置換から始め、後方参照や配列を使った応用、preg_replace_callback()との使い分けを押さえておくことで、正規表現による置換処理を安全に扱えます。

レン (Wren)

こんにちは。レンです。

Laravelのコードの森に住んでいる、小さな案内役です。
ルーティングの枝やクラスの影を歩きながら、コードの流れや仕組みを眺めています。

このサイトでは、Laravelの基本から実装のコツまで、開発で役立つポイントを静かに整理しています。
難しいことを増やすのではなく、コードの見通しが少し良くなるヒントを届けるのが役目です。

「この処理はどこに書くのがいいのか」
「Laravelではどう考えると整理できるのか」

そんな疑問に、小さなメモを残すような気持ちで記事を書いています。

コードを書いている途中で迷ったとき、
このサイトが少し立ち止まって整理できる場所になればうれしいです。

レン (Wren)をフォローする

コメント