PHPで文章中の単語リストを置換するいろいろな方法
PHPでテキスト文章の置換を行う際に「単語のリストを全てリンクに置き換えたい」とか「最初に一致した場合だけ置き換えたい」といった事を実現する方法を紹介しましょう。
今回は実験として「カーテン関連の文章から『カーテン』『カーテンレール』にWikipediaのリンクを貼る」ということをやってみたいと思います。
置き換え候補の日本語ワードと、文章を用意
まず置き換え用の単語リストは配列形式にしておくと何かと便利。
特定の文章から名詞のような単語のみを抜き出す場合はMeCabを使ったテクニックを前回紹介しましたので、そちらを参照してください。
$meisi = array("カーテン", "カーテンレール"); $meisi = array_map('preg_quote', $meisi);
preg_quote()を実行している理由は、単語リストの中に正規表現で不正な文字があったら無害化するためです。
次に、置き換え対象の文章を用意します。 適当にカーテンに関する文章を作ってみます。
$str = "カーテンを付けるためには、カーテンレールが欠かせません。 でも、新築の戸建てやマンションにはカーテンレールが付いていません。 カーテンがないとご近所から丸見えで夜も眠れません。";
これで材料が揃いましたね。 ではさまざまな置き換えパターンを見ていきましょう。
1.とにかく単語リストに一致した箇所はすべて置き換える場合
この場合は、単語リストをimplode(“|”, $meisi)でくっつけて、preg_replace_callback()で置き換えます。 「m」と「u」のスイッチはそれぞれ複数行、UTF-8に対応させるためです。
なぜpreg_replace() ではなく preg_replace_callback() という面倒な関数にしたかというと、Wikipediaのリンクを作成する際に日本語部分をURLエンコードするためのurlencode() を利用してリンクテキストに置換するためです。
PHPマニュアル:preg_replace_callback()
正規表現検索を行い、コールバック関数を使用して置換を行います。
この関数の動作は、ほぼ preg_replace() と同じですが、 replacement の代わりに callback を指定するところが異なります。
$regexp = "/(".implde("|", $meisi).")/mu"; $str = preg_replace_callback( $regexp, create_function( '$matches', '$txt=$matches[0]; return "<a href="http://ja.wikipedia.org/wiki/".urlencode($txt)."" rel="nofollow">".$txt."</a>";' ), $str );
実行結果はこちら。
カーテンを付けるためには、カーテンレールが欠かせません。
でも、新築の戸建てやマンションにはカーテンレールが付いていません。
カーテンがないとご近所から丸見えで夜も眠れません。
2.単語が最初に登場した箇所だけ置き換える場合
文章中にあんまり外部リンクが増えすぎるのは困りものだということで、各単語を1回だけ置き換える場合は、正規表現を配列化し、preg_replace_callback() の第4引数に回数制限用の「1」を設定することで実現できます。
$regexp = array(); foreach($meisi as $m) { array_push($regexp, "/".preg_quote($m)."/mu"); } $str = preg_replace_callback( $regexp, create_function( '$matches', '$txt=$matches[0]; return "<a href="http://ja.wikipedia.org/wiki/".urlencode($txt)."" rel="nofollow">".$txt."</a>";' ), $str, 1 );
実行結果はこちら。
カーテンを付けるためには、カーテンレールが欠かせません。
でも、新築の戸建てやマンションにはカーテンレールが付いていません。
カーテンがないとご近所から丸見えで夜も眠れません。
リンク先を変えれば内部リンクも思いのままです。 こういう役に立つスキルをどんどん身につけて紹介していければと思います。 よろしく!
2011-04-16