URLをリンクし、さらにデコードしてタイトル表記にする

なんっていうか説明し辛い表現だが。

正規表現を使いURLを拾い上げてリンクをつけ、さらにその中にURLのタイトルとして使える物があればそれも使う。

つまりは、アマゾンなどの検索リンク貼り付けると

http://www.amazon.co.jp/s/ref=nb_sb_noss?__mk_ja_JP=%83J%83%5E%83J%83i&url=search-alias%3Daps&field-keywords=%83e%83X%83g

こうなるのを、

<a href="http://www.amazon.co.jp/s/ref=nb_sb_noss?__mk_ja_JP=%83J%83%5E%83J%83i&url=search-alias%3Daps&field-keywords=%83e%83X%83g" target="_blank">http://www.amazon.co.jp/s/ref=nb_sb_noss?__mk_ja_JP=%83J%83%5E%83J%83i&url=search-alias%3Daps&field-keywords=%83e%83X%83g</a>

こうする。さらに、アマゾンのリンクは「field-keywords=%83e%83X%83g」の部分に検索した文字列があるので、こいつを抜き出しデコードしてこのような形にする。

<a href="http://www.amazon.co.jp/s/ref=nb_sb_noss?__mk_ja_JP=%83J%83%5E%83J%83i&url=search-alias%3Daps&field-keywords=%83e%83X%83g" target="_blank">テスト</a>

URLをリンク化する正規表現は少し検索すればすぐ出てくる。私はこのようにしている。

$URL = "http://www.amazon.co.jp/s/ref=nb_sb_noss?__mk_ja_JP=%83J%83%5E%83J%83i&url=search-alias%3Daps&field-keywords=%83e%83X%83g"
$URL = preg_replace("/(https?.*?)(?= | |n|r)/ium", "<a href="&quot;$1&quot;" target="&quot;_blank&quot;">$1</a>", $URL);

「http」もしくは「https」から始まり、改行、スペース手前に至るまでの文字列をリンクとして処理する。(?=)は肯定的先読みで、スペースや改行自体にマッチングするわけではなく、その手前、文字と文字の間にマッチングする。

正規表現の先読み・後読みを極める! – あらびき日記
柔軟性の高い正規表現を書こうとすると,避けて通れないのが先読み・後読みです. 先読み・後読みに関して,いままではとりあえず的な理解をしていたのですが,それだと説明できない正規表現に遭遇したので,説明 …
とても理解しやすかったです。ありがとうございます

さらに、「リンク処理がされていて」なおかつ「keywords=」がURLに含まれている文字列を探し出し、そのテキスト行を処理する正規表現をかける。(「field-keywords=」でないのは、他の検索サービスなどで「keywords=」を利用している場合があるからで、そちらも同時に処理できてしまえば手間が減るから)

$URL = preg_replace("/(?<="_blank">)(https?.*?)(?<=keywords=)(.*?)(?=</a>|&)/iume", '"URL:".urldecode("$2")', $URL);

少しややこしい処理になっている。ひとつひとつ見ていこう。まずパターンから。

<a href="http://www.amazon.co.jp/s/ref=nb_sb_noss?__mk_ja_JP=%83J%83%5E%83J%83i&url=search-alias%3Daps&field-keywords=%83e%83X%83g" target="_blank">http://www.amazon.co.jp/s/ref=nb_sb_noss?__mk_ja_JP=%83J%83%5E%83J%83i&url=search-alias%3Daps&field-keywords=%83e%83X%83g</a>

肯定的後読み。"_blank">の「後」にマッチングする。
(?<="_blank">)
<!-- 正確には「"_blank">」と「http:」の間 -->
↓
http://www.amazon.co.jp/s/ref=nb_sb_noss?__mk_ja_JP=%83J%83%5E%83J%83i&url=search-alias%3Daps&field-keywords=%83e%83X%83g</a>
http、httpsから始まり、さらに「keywords=」がある場合に「keywords=」の「後」にマッチングする。
https?.*?(?<=keywords=)
↓
<!-- 正確には「keywords=」と「%83e%83X%83g</a>」の間 -->
%83e%83X%83g</a>

「keywords=」の後の文字列から、</a>もしくは$の手前までを$1に収容する。
(.*?)(?=</a>|&)
↓
%83e%83X%83g

以上でマッチングされる文字列は
$1 = %83e%83X%83g

処理は簡単だが、「%83e%83X%83g」をデコードする必要があり、そのためには処理の中でurldecode()を利用する。パターン修飾子「e」をつける必要がある。

'"URL:".urldecode("$1")'

そして実際の処理はこうなっている。テキストだだと味気ないので「URL:」をつけるようにしてみた。処理全体をシングルクォーターで加工のを忘れずに。