【PHP入門2021】正規表現での文字列置換にコールバックが使えるpreg_replace_callback関数

PHP

preg_replace_callback関数の基本構文

preg_replace_callback関数は正規表現を使って文字列を置換できるのに加えて、コールバック関数を利用できます。

簡単に言うと置換の自由度が無限大になります。正規表現でマッチさせた文字列を使って、自由にPHPプログラムで判定書き換え処理ができます。

preg_replace_callback ( string|array $pattern , callable $callback , string|array $subject , int $limit = -1 , int &$count = null , int $flags = 0 )

置換元の文字列が複数あっても全て変換されます。日本語などのマルチバイト文字列も変換可能です。

また配列の中身を置換したり、置換元と置換先のを配列で複数指定することもできます。

正規表現自体の使い方はこちらを参考にしてみてください。

パラメータ

名前 初期値 説明
string|array $pattern ●●●●
callable $callback
string|array $subject
int $limit -1
int&$count null
int $flags 0

preg_replace_callbackに渡すコールバック関数の書式

function ( array $matches ){
	return 変換した文字列;
}

$matchesの中にはマッチした文字列が配列で含まれています。

$matches[0]→マッチした文字列全部
$matches[1]→グループ化した1番目のマッチ文字列
$matches[2]→グループ化した2番目のマッチ文字列
 …

返り値(戻り値)

説明
string|array|null 置換後の対象文字列、配列。エラーの場合はnull

preg_replace_callback関数の使い方

文字列を正規表現でマッチした部分だけ大文字に置換するサンプルソースコード

echo "文字列を正規表現でマッチした部分だけ大文字に置換する" . PHP_EOL;
$str = "私はphpの初心者です";
echo $str . PHP_EOL;
$str = preg_replace_callback('/php/i', function ($matches) {
			return strtoupper($matches[0]);
		}, $str);
echo $str . PHP_EOL;
私はphpの初心者です
私はPHPの初心者です

正規表現にマッチした中の特定の文字列を含む時だけ置換するサンプルソースコード

ある文字列の中にURLを複数含む場合特定の条件化だけaタグをつけてリンク化してみます。

echo "特定のURLだけ<a>タグに置換する" . PHP_EOL;
$str = "このページのURLはhttps://trios.pro/です。https://trios.comではありません。";
echo $str . PHP_EOL;
$str = preg_replace_callback('|https*?\://[-_.!~*a-zA-Z0-9;/?:@&=+$,%#]+|', function ($matches) {
			print_r($matches);
			if(strpos($matches[0], "trios.pro") !== false) { //trios.proが含まれていたら
				return "<a href=\"{$matches[0]}\">{$matches[0]}</a>"; //タグを付けて返す
			}
			return $matches[0]; //そのままの文字列を返す
		}, $str);
echo $str . PHP_EOL;
特定のURLだけ<a>タグに置換する
このページのURLはhttps://trios.pro/です。https://trios.comではありません。
Array
(
    [0] => https://trios.pro/
)
Array
(
    [0] => https://trios.com
)
このページのURLは<a href="https://trios.pro/">https://trios.pro/</a>です。https://trios.comではありません。

文章からURL文字列を抜き出してドメインだけ抜き出すサンプルソース

正規表現とコールバック、さらにグループキャプチャを組み合わせることで様々な表現が可能になります。

正規表現だけでやろうとすると修正できないほど複雑になりかねないのでそれぞれをシンプルに他人が見てもわかりやすい記述を心がけましょう。

echo "文章からURL文字列を抜き出してドメインだけ抜き出す" . PHP_EOL;
$str = "このページのドメインはhttps://trios.pro/です。https://trios.comではありません。";
echo $str . PHP_EOL;
$str = preg_replace_callback('|(https*)?\://([-_.!~*a-zA-Z0-9;/?:@&=+$,%#]+)|', function ($matches) {
	print_r($matches);
	if(isset($matches[2])){
		$domain = preg_replace('|^([^/]+)/.*$|', '${1}', $matches[2]);
		echo "抜き出したドメイン→{$domain}" . PHP_EOL;
		return $domain;
	}
	return $matches[0]; //そのままの文字列を返す
}, $str);
echo $str . PHP_EOL;
文章からURL文字列を抜き出してドメインだけ抜き出す
このページのドメインはhttps://trios.pro/です。https://trios.comではありません。
Array
(
    [0] => https://trios.pro/
    [1] => https
    [2] => trios.pro/
)
抜き出したドメイン→trios.pro
Array
(
    [0] => https://trios.com
    [1] => https
    [2] => trios.com
)
抜き出したドメイン→trios.com
このページのドメインはtrios.proです。trios.comではありません。

関連する関数

str_replace

正規表現の基本

PHPの正規表現が使える関数一覧(PCRE関数)

preg_***の「preg」の名前の由来

preg_からはじまる関数はPCRE関数といい、PCREというのは正規表現の仕様の種類の一つです。PCREは「Perl Compatible Regular Expressions」の略で、perl互換の正規表現という意味です。

すなわち、preg_***関数のpregとは「PCRE + Regular + Expression」の略です。
(PHPのPだと思ったらPerlのPだったんですね・・・)

preg_match/preg_match_all

正規表現パターンによる検索全般。マッチするか確認したり、マッチした数や文字列を取得する。

preg_split

文字列を正規表現によって分割して配列に変換する。explodeのイメージ。

preg_replace

正規表現パターンにマッチした文字列を指定文字列に変換する。マッチしないと元の文字列が返る。空を返したいならpreg_filter

preg_replace_callback

preg_replaceにコールバックを渡してより柔軟な変換ができる。

preg_filter

正規表現パターンにマッチした文字列を指定文字列に変換する。マッチしないと空の文字列が返る。元の文字列を返したいならpreg_replace

preg_last_error

直近の正規表現エラーを返す

preg_quote

ある文字列を正規表現のエスケープ処理する。正規表現パターン作成時に「この文字列はこのまま扱いたいので正規表現として機能してほしくない」という場合に使う。

コメント

タイトルとURLをコピーしました