preg_replace e修飾子で置換と計算、preg_replace_callback() に置き換え

更新:

PHPの preg_replace() e修飾子で置換しつつ計算する。PHP 7用に preg_replace_callback() に置き換え。

preg_replace e修飾子の置換と演算(PHP 5.x)

HTML中にある以下のような画像のタグ
<img src="./test.jpg" width="640" height="480" alt="test">
<img src="./test.jpg" width="320" height="240" alt="test">
に置換するために以下のようなコードを記述。
$body = preg_replace('/<img (.+) width=\"(\d{1,4})\" height=\"(\d{1,4})\"/e',
	'"<img $1 width=\"" . round("$2"/2) . "\" height=\"" . round("$3"/2) . "\""',
	$body);
要するに画像のサイズが半分になるように置換する。
preg_replace_callback() を使っても良いが、わざわざ関数を用意するほどでもないので preg_replace() で処理した。
preg_replace() で演算するには、正規表現を '(シングルクォーテーション)で囲み、コードとして実行するために /e を書く。
置換の規則も ' で囲み、文字列の部分は " で囲む。
$body は <body> 内のすべてのテキストが入っている。
$1、$2、$3 はそれぞれ正規表現に一致した文字列。
画像のサイズは小数点があってもウェブブラウザで表示できるが、一応 round() を使って整数にした。
ただし、preg_replace() のe修飾子は、任意のPHPコードが実行されてしまう危険性があるためPHP 7で廃止になり、php.netでは代わりに preg_replace_callback() の使用を勧めている。


preg_replace_callback で置換

preg_replace() のe修飾子廃止によりコードを変えた。
$body = preg_replace_callback('/<img (.+) width=\"(\d{1,4})\" height=\"(\d{1,4})\"/',
	function($m){
		return "<img $m[1] width=\"" . round($m[2]/2) . "\" height=\"" . round($m[3]/2) . "\"";
	},
	$body);
ただし、無名関数はPHP 5.3から使用でき、PHP 5.2以下だとエラーになる。
古いPHPでは以下のように書く。
function img_replace($m){
	return "<img $m[1] width=\"" . round($m[2]/2) . "\" height=\"" . round($m[3]/2) . "\"";
}

$body = preg_replace_callback('/<img (.+) width=\"(\d{1,4})\" height=\"(\d{1,4})\"/',
	'img_replace',
	$body);
http://php.net/manual/ja/reference.pcre.pattern.modifiers.php
http://php.net/manual/ja/function.preg-replace-callback.php

このエントリーをはてなブックマークに追加