使い道あるの?
正確性を期すと、PHPマニュアルには「正規表現構文をクオートする」とあります。なので厳密には正規表現用の関数ですが、正規表現構文の特殊文字は「. \ + * ? [ ^ ] $ ( ) { } = ! < > | : -
」の記号のことなので、正規表現構文の特殊文字≒記号という大まかな捉え方でも大きな問題はありません。
この関数は単体ではあまり使い道がなさそうですが、preg_match
関数、preg_match_all
関数、preg_replace
関数等と組み合わせると威力を発揮します。
具体的にはhtmlタグの差し替えを容易にしてくれます。
preg_quote関数を使ってみる
例えば下記のhtmlファイルのimgタグの内容を変更したいとします。imgタグの内容がすべて同じであれば、変更は容易いのですが、多くの場合でそうであるように画像URLの内容はURLなどがそれぞれ違います。
<!-- img.html -->
<img src="http://hoge.hoge.com/?image=sky_image.jpeg">
<img src="http://hoge.hoge.com/?image=ground-12_image.png">
<img src="http://hoge.hoge.com/?image=sea_image.bmp">
<img src="http://hoge.hoge.com/?image=road.svg">
このhtmlに「拡張子ごとに画像URL構造の変更」を行いたい場合を考えてみます。
元の動的URL構造から
http://hoge.hoge.com/?image=sky_image.jpeg
こうした拡張子ごとのディレクトリの静的URL構造に変えたいのです。
http://hoge.hoge.com/jpeg/sky_image.jpeg
これを実現させるためには全体のimgタグに一つ一つに処理をするため、 preg_match_all関数をつかってタグをマッチさせていくことになるかと思いマス。
下記の正規表現でマッチさせられるはず。(サブグループで拡張子、ファイル名を取得しています)
$html = file_get_contents("img.html");
$regEx = "/<img\ssrc=\"http:\/\/hoge\.hoge\.com\/\?image=([_\-a-z0-9]+\.([jpegbmnsv]{3,4}))\">/";
preg_match_all($regEx, $html, $match, PREG_SET_ORDER);
さてpreg_match_all
関数で無事imgタグをマッチさせることができたのですが、こんどはこれらのマッチしたimgタグを正規表現として使って、preg_replace
関数にて元のimgタグを新しいタグに差し替えを行います。
preg_replace関数
preg_replace
関数は正規表現にて、マッチした部分を指定した文字列で差し替えます。
しかしhtmlタグは上記で説明したとおり正規表現構文の特殊文字である「. \ + * ? [ ^ ] $ ( ) { } = ! < > | : -
」のほとんどを含みます。マッチしたままの状態でのimgタグはこれらの特殊文字をふんだんに含んでいます。
もしこのままpreg_replace
関数に与えてしまうとそれらの特殊文字は正規表現構文の特殊文字であると認識され、期待した動作にはなりません。
preg_quote関数の真価
そんな時の為に役立つのがpreg_quote
関数です。
preg_quote
関数は特殊文字をバックスラッシュ(\
)でクオートします。これは「エスケープする」と言う言い方と同義です。
特殊文字はエスケープされると「その字面どおりの文字」として認識されます。
例えば「*
」は正規表現では「0回以上の繰り返し」という意味になりますが、バックスラッシュでエスケープ「 \*
」すると単に「文字としてのアスタリスク」と認識されます。
imgタグを例にしてみます。
<img src="http://hoge.hoge.com/?image=sky-image.jpeg">
このタグには「0回または1回の出現」を意味する「 ?
」や「改行以外の1文字」と意味する「 .
」があるので、このままの形で正規表現として使うとこのタグの字面通りの文字列にはマッチしません。
それをpreg_quote
関数でクオートしてあげるとこのようになります。
\<img src\="http\:\/\/hoge\.hoge\.com\/\?image\=image\.jpeg"\>
特殊文字はすべてクオートされ、「 ?
」や「 .
」もその字面通りの文字として認識されるようになりました。
では実際に一連の処理をコードにしてみました。
string(209) "<img src="http://hoge.hoge.com/jpeg/sky_image.jpeg">
<img src="http://hoge.hoge.com/png/ground-12_image.png">
<img src="http://hoge.hoge.com/bmp/sea_image.bmp">
<img src="http://hoge.hoge.com/svg/road.svg">
ちゃんとURLが期待通りに差し替わっています。わ〜い。
preg_quote
関数が無いと、自分でエスケープをする関数なりを作らなくてはならないので不便ですがpreg_quote
関数なら一発でエスケープをしてくれます。
便利デス。
補足・ハマったポイント
preg_quote関数の第二引数
preg_quote
関数の第二引数で/
を指定しているのは、デフォルトではエスケープされないからです。
本来はデリミタをエスケープするためにの引数なのですが、URLの/
をエスケープするにも使えるので、指定しておきます。指定しないと/
がエスケープさせずエラーが出ます。
PHP Warning: preg_replace(): Unknown modifier '/' in /home/mino/php_quoet.php on line 31
PHP Warning: preg_replace(): Unknown modifier '/' in /home/mino/php_quoet.php on line 31
PHP Warning: preg_replace(): Unknown modifier '/' in /home/mino/php_quoet.php on line 31
PHP Warning: preg_replace(): Unknown modifier '/' in /home/mino/php_quoet.php on line 31
NULL
まとめ
preg_quote
関数は正規表現構文の特殊文字をクオート(エスケープ)する- 単体ではちょっとアレだが、他の
preg
系関数と併用すると真価を発揮する - 正規表現を用いたhtml変更をしやすくしてくれる関数