正規表現でURLをリンクに変換する

(1/1)
掲示板やブログで、"http://~" ではじまる文字列を自動的にハイパーリンクに変換してくれるところが多い。これを PHP で実装しようとする際、正規表現が威力を発揮する。

URLで使える文字

URL を正規表現で表す前に、URL で使えるすべての文字の種類を把握しておく必要がある。
URL の書き方は、RFC 1738 Uniform Resource Locators (URL)和訳】に定義されている。これによると、
"http(s)://" 以降に記述できる文字は、英数字(大文字・小文字)と記号類(- _ . ! ~ * ' ( ) ; / ? : @ & = + $ , % #)であることがわかる。

これを正規表現で表すと、

/https?\:\/\/[\-_\.\!\~\*\'\(\)a-zA-Z0-9\;\/\?\:\@\&\=\+\$\,\%\#]+/i


となる。順に説明していこう。

今回使った正規表現

?
直前1文字の0または1回の繰り返し。
ここでは、http, https の両方にマッチする。
[ ]
文字クラス。 この中に記述された文字の並びのうちの1文字を表す。
-
文字の範囲指定。
a-z はアルファベット小文字すべてに、A-Zはアルファベット大文字すべてに、0-9は数字すべてにマッチする。
+
直線1文字の1回以上の繰り返し。 ここでは、文字クラス[...]に記述された文字、いずれかの1回以上の繰り返し――すなわち、URL 文字列にマッチすることになる。
( )
サブパターン。 マッチングだけであれば不要だが、置換を行うために、マッチした部分文字列に番号を付けてやる必要がある。その場合にサブパターンを用いる。

サンプル・プログラム

サンプル・プログラムの解説:準備

関数  mb_internal_encoding  により、内部処理は UTF-8 を指定する。
念のため、関数  mb_regex_encoding  により、正規表現処理も UTF-8 を指定しておく。

このプログラムは、入力部と出力部を同じファイルで処理するため、form タグの飛び先を自分自身 MYSELF にする。

検索パターンを変数 $pat に、置換パターンを $rep に設定しておく。
ereg 系正規表現関数では、マッチしたサブパターンには、順番に ¥1, ¥2, ¥3‥‥という符号が付けられ、置換パターンで置き換えを行うことができる。

0008: // 初期化処理 ================================================================
0009: define('INTERNAL_ENCODING', 'UTF-8');
0010: mb_internal_encoding(INTERNAL_ENCODING);
0011: mb_regex_encoding(INTERNAL_ENCODING);
0012: define('MYSELF', basename($_SERVER['SCRIPT_NAME']));
0013: $pat  = '/(https?\:\/\/[\-_\.\!\~\*\'\(\)a-zA-Z0-9\;\/\?\:\@\&\=\+\$\,\%\#]+)/i';  //検出パターン
0014: $rep  = '<a href="\1">\1</a>';          //置換パターン

サンプル・プログラムの解説:URLの置換

実際に置換を行うのは、関数  preg_replace  である。

また、リセットボタンを押すことで、すべてのエリアをクリアするようにしてある。HTML のリセットボタンではすべてクリアできないので、reset が POST 渡しされたときに PHP でクリアするようにしてある。

0109: // メイン・プログラム =======================================================
0110: if (isset($_POST['reset'])) {
0111:     $sour = '';
0112:     $dest = '';
0113: else {
0114:     $sour = isset($_POST['sour']) ? mb_convert_encoding($_POST['sour'], 'UTF-8', 'auto') : '';
0115:     $dest = isset($_POST['dest']) ? mb_convert_encoding($_POST['dest'], 'UTF-8', 'auto') : '';
0116:     $sour = htmlspecialchars($sour);         //XSS対策
0117:     $dest = preg_replace($pat$rep$sour);
0118: }
0119: 
0120: $HtmlBody = makeCommonBody($sour$dest);
0121: 
0122: // 表示処理
0123: echo $HtmlHeader;
0124: echo $HtmlBody;
0125: echo $HtmlFooter;

(この項おわり)
header