preg_matchで複数一致した場合の処理

このQ&Aのポイント
  • preg_matchを使用して複数のURLパターンに一致する場合の処理について調査しています。
  • 現在の実装では、画像サービスのURLが一つしか変換されず、複数のURLに対応できていません。
  • 質問者は、2つ目の画像のリンク先を正しく設定する方法について助言を求めています。
回答を見る
  • ベストアンサー

preg_matchで複数一致した場合の処理

いつも大変お世話になっております。 「Twitpic 等の画像投稿サービスのサムネイル画像の URL」 http://blog.irons.jp/2009/12/23/twitter_thumb_url/ 上記のサイトをそのまま参考にしまして以下のようなことをしようと思っています。 ・テキストに画像サービスのURLが記載されていたらサムネイル画像を表示 ・普通のURLが含まれていた場合は普通のリンクとして表示 ―――――――――――――――――――― $text = "テキスト http://twitpic.com/xxxxxx http://twitpic.com/yyyyyy http://p.twipple.jp/zzzzzz http://example.com/aaaaaa"; $patterns = array( // twitpic array('/http:\/\/twitpic[.]com\/(\w+)/', '<img src="http://twitpic.com/show/thumb/$1" width="150" height="150" />'), // ついっぷる フォト array('/http:\/\/p[.]twipple[.]jp\/([\w]+)/', '<img src="http://p.twipple.jp/show/large/$1" />'), // 通常URL array('/((?<!")https?:\/\/[a-zA-Z0-9\.\/~_?&=%@#!;*:-]+)/', '$1'), ); foreach ($patterns as $pattern) { if (preg_match($pattern[0], $text, $matches)) { $url = $matches[0]; $text= preg_replace($pattern[0], '<a href="'. $url .'" target="_blank">'.$pattern[1]."</a> ", $text); } } echo $text; ―――――――――――――――――――― これを実施しましたところ、 テキスト [twitpic画像xxxxxx] [twitpic画像yyyyyy] [ついっぷる画像zzzzzz] [通常URLのリンクaaaaa] と、表示自体は希望している形に出来ました。 しかし、[twitpic画像yyyyyy]の部分において、画像はyyyyyyが表示されているのですが、リンク先がhttp://twitpic.com/xxxxxxと、一つ目の画像になってしまっているのです。 おそらく、preg_matchでヒットした最初のURLを変換対象にしてしまっていると思うのですが、 preg_match_allにしたり、様々なやり方で工夫したのですが、どうしても解決できなく、質問させて頂きました。 この場合、2つ目の画像のリンク先をhttp://twitpic.com/yyyyyy へ向けるにはどのように修正したらよろしいでしょうか。 何卒宜しくお願い致します。

  • PHP
  • 回答数1
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
  • t_ohta
  • ベストアンサー率38% (5059/13223)
回答No.1

$text = "テキスト http://twitpic.com/xxxxxx http://twitpic.com/yyyyyy http://p.twipple.jp/zzzzzz http://example.com/aaaaaa"; $patterns = array( // twitpic array('/(http:\/\/twitpic[.]com\/(\w+))/', '<img src="http://twitpic.com/show/thumb/$2" width="150" height="150" />'), // ついっぷる フォト array('/(http:\/\/p[.]twipple[.]jp\/([\w]+))/', '<img src="http://p.twipple.jp/show/large/$2" />'), // 通常URL array('/((?<!")https?:\/\/[a-zA-Z0-9\.\/~_?&=%@#!;*:-]+)/', '$1'), ); foreach ($patterns as $pattern) { $text= preg_replace($pattern[0], '<a href="$1" target="_blank">'.$pattern[1]."</a> ", $text); } echo $text;

doomdoom
質問者

お礼

ありがとうございます! 希望通りに表示出来ました。 なるほど、全体を括弧で囲んで$1にすれば変換が出来るのですね。 勉強になりました。ありがとうございました。

関連するQ&A

  • preg_matchでエラーが出ます。

    「PHP Warning: preg_match() expects parameter 2 to be string, array given in~」というエラーが出てきて困っています。 該当する行は下記です。 if( preg_match("/http:\/\/aa.com\//" , $url ) ) 真ならば上手く行くのですが、違うアドレスだった場合、エラーが出ます。 当方PHP初心者ですが、助言をお願いします。

    • ベストアンサー
    • PHP
  • preg_matchの検索について

    <?php  header("content-type: text/plain");  $pat = '/<a href="([^"]*)">/';  $html="<p><a href=\"http://test.net/test3.html\">リンク</a></p>";  preg_match($pat,$html,$match); print_r($match); ?> 上記正規表現プログラムを作成しました。 結果を確認したところ、 Array ( [0] => <a href="http://test.net/test3.html"> [1] => http://test.net/test3.html ) このようにでるのですが、[1]つめが存在している理由がわかりません。 [0]だけが出てくると思っていたのですが、なぜ、[1]はどのような理由で作成されたのでしょうか。 ご教授よろしくお願いします。

    • ベストアンサー
    • PHP
  • preg_matchでのマッチが正しくされない

    メールヘッダを解析して処理させるプログラムを作成しています。 ヘッダから件名を取得するために以下のコードを記述しました。 $head = 'Return-Path: Delivered-To: hoge@hogehoge.com Received: from docomo.ne.jp (mail102.docomo.ne.jp [203.138.203.2]) by www.hogehoge.com (Postfix) with ESMTP id C73904003B for ; Fri, 25 Mar 2011 16:32:19 +0900 (JST) Date: Fri, 25 Mar 2011 16:32:24 +0900 (JST) From: huga@hogehoge.com To: hoge@hogehoge.com Subject: =?iso-2022-jp?B?GyRCJFskMiRbJDIkVSQsJFUkLBsoQg==?=hogehogehugahuga =?iso-2022-jp?B?GyRCJFskMiRbJDIkVSQsJFUkLBsoQg==?= Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset="iso-2022-jp" Content-Transfer-Encoding: 7bit X-Virus-Scanned: clamav-milter 0.96.3 at MCN X-Virus-Status: Clean' $ptrn = '/Subject:([\s\t]*=\?iso-2022-jp\?[BQ]\?([^\?]+)\?=)+.* Message\-ID/i'; preg_match($ptrn, $head, $regs); var_dump(regs[0]); $headに別関数で取得したメールのヘッダ情報、$ptrnに正規表現での一致条件を書き出しました。 PHPの正規表現チェッカーでは正常にマッチしたのですが、preg_matchで動作させるとマッチしてくれません。 何がまずいのでしょうか? 正しくマッチさせる方法をご回答お願いします。

    • ベストアンサー
    • PHP
  • preg_replace

    $img_ref = '<a target="_blank" href="http://aaa/aaa/.com/'.$_POST[bbs].'/img/'.$_POST['key'].$imgnum.$tail.'">'; 上記みたいな画像掲示板のスクリプトの画像URLリンク先を示す箇所で、preg_replaceを使って「http://」と「aaa/aaa.com」の間にbbb/bbb/image.cgi?を入れたいと思います。 ↓こんな感じかなーと思いつつあやっぱりできません。 $img_ref = preg_replace("/(https?):\/\/([\w;\/\?:\@&=\+\$,\-\.!~\*'\(\)%#]+)/", "<a href=\"$1://bbb/bbb/image.cgi?$2\" target=\"_blank\">", $img_ref); だれか知ってる方何卒宜しくお願いします。

    • ベストアンサー
    • PHP
  • preg_replace_callback が渡す変数の扱い

    preg_replcace_callback を使用して、<a>タグ内のURLの字数を制御するコードに取り組んでいます。詳しい方アドバイスしてくださると助かります。 下のコードの、shorten(カスタム関数)に渡されるデータが配列なのですが、並列に並んだ配列のようなのです。echo をかけてみると、ArrayArray と表示されます。しかし、Array([0]=>Array [1]=>Array) ではないので、どうやって 処理をかけて return すればよいのか途方にくれています。 もしよい方法をご存知の方おられましたらどうぞよろしくお願いいたします。 <? $str = <<<HERE //長いURLのサンプルです。ここの掲示板の処理で途中で表示がカットされていますが、<a href="http://長いURL">http://長いURL</a>という構成になっています。 <a href="http://gooooooooooooooooooooooooooooooooooogle.co.jp">http://gooooooooooooooooooooooooooooooooooogle.co.jp[</a> <a href="http://yahooooooooooooooooooooooooooooooooooo.co.jp">http://yahooooooooooooooooooooooooooooooooooo.co.jp</a> HERE; $pattern = "#<a(.*?)>(.*?)<\/a>#s"; $str = preg_replace_callback($pattern, 'shorten', $str); echo $str; function shorten($matches) { foreach($matches as $index => $match) { if (strlen($match) > 20) { $matches[$index] = substr($match, 0, 20) . '....'; } } return $matches; } ?>

    • ベストアンサー
    • PHP
  • htmlソースからタグ内のテキストを配列に

    お世話になっております。 $addfname = trim($_POST["url"]); $html = file_get_contents($addfname); $html = mb_convert_encoding($html,"EUC-JP","auto"); 以上のように、フォームに入力されたURLを読み込み、各タグ内に記述されたテキストなどを排出(配列に格納)しようと思い、<h2></h2>のようにh2タグで囲まれたテキストは、 $pattern = '/<h2>(.*)<\/h2>/is'; $match = array(); preg_match_all($pattern, $html, $match, PREG_SET_ORDER); $h2text1 = str_replace("<h2>", "", $match4[0][0]); $h2text2 = str_replace("</h2>", "\t", $h2text1); $h2array = explode("\t", $h2text2); $h2cnt = count($h2array)-1; とすることで、なんとか配列に格納することが出来ました。 が、しかし、CSSなどで、<h2 class="~"></h2>となっていたりすると、正常に読み込むことが出来ず、</h2>タグ以降のテキストなども読み込んでしまいます。 配列に格納する方法も、どこかぎこちないように思えたりもしますが、以上のような、idや、classなど、<h2>だけで括られている以外のテキストなども読み込むには、どのようにしたら宜しいのでしょうか? お忙しいなか恐縮ですが、アドバイスのほどよろしくお願い申し上げます。

    • ベストアンサー
    • PHP
  • preg_replace関数のtarget属性

    ○質問の主旨 preg_replace関数の引数の一部にある<a>タグ内の target属性を"_blank"にしていますが、新しいウィンドウが開かず、 元の画面のまま、href属性のリンク先に遷移します。 新しいウィンドウにhref属性のURLを表示させるためには どうすれば良いでしょうか? ご存知の方がいらっしゃいましたら、ご教示願います。 ○質問の補足 現在、以下のようなコードを用いています。 $tweet['text']=preg_replace("/(http:\/\/t.co\/[a-zA-Z0-9]{10})/", "<a href=\"\\0\" target=\"_blank\">\\0</a>", $tweet['text']); $tweet['text']とは、Twitter RESTAPI1.1のGET search/tweetsから ひっぱってきた文字列で、ツィート本文のことです。 コード全体の意味は、 「ツィート本文にhttp://t.co/○○○○○○○○○○という文字列があれば、 そのリンク先にtarget=_blankで遷移しなさい」 ということになります。 以上、よろしくお願い申し上げます。

    • ベストアンサー
    • PHP
  • HTML文書内の相対URLを絶対URLに変換する方法

    現在,PHPを使って擬似的なプロクシサーバーを作成しています. 動作としては,フォームにURLを入力し,送信,受け取ったPHP側でfile_get_contentsでHTMLデータを受信し,それを出力する物です. ところが,当然ではありますが相対URLでリンクされていると,その画像やリンク先に遷移することができません. そこで,リンクをすべて絶対URLに置き換えたいのですが,現在では上手く置き換わりません.(置き換わらない例:https://ssl.kakaku.com/auth/id/login.asp の画像の一部など) どなたかご教授いただけると幸いです. よろしくお願いします. なお,現在の処理は以下のようになっています. 使用関数 HTMLSQL,make_url(下記URLにあるgetAbsURL関数) http://www.jonasjohn.de/lab/htmlsql.htm http://www.phppro.jp/qa/2290 --------------------------------------------------------- // HTMLSQLオブジェクトの生成 $htmlsqlObj = new htmlsql(); // 相対URLのリンクを絶対URLへ変換 if(!$htmlsqlObj->connect("string",$html_data)) { error("エラー",__LINE__); } // 絶対URL化ターゲットタグ $target_tags = array("a"=>"href","link"=>"href","img"=>"src","form"=>"action","script"=>"src","input"=>"src"); $i =0; while(list($key,$val) = each($target_tags)) { if(!$htmlsqlObj->query("SELECT {$val} FROM {$key}")) { error("エラー",__LINE__); } $link_array[$i] = $htmlsqlObj->fetch_array(); $i++; } // 絶対URL変換 for($i = 0;$i < count($link_array);$i++) { for($j = 0;$j < count($link_array[$i]);$j++) { while(list($key,$val) = each($link_array[$i][$j])) { // 相対パス以外を排除 if(!preg_match("/(http:\/\/)|(ftp:\/\/)|(mailto:)|#/",$val) && $val != "/" && $val != "") { // 絶対URL化 $full_url = make_url($url,$val); $val_new = preg_quote($val,"/"); $html_data = preg_replace("/{$val_new}/",$full_url,$html_data); } } } }

    • ベストアンサー
    • PHP
  • HTMLをPHPでJSONにして返すには

    jqueryでurlをPHPに送って、そのurlのhtmlファイルから、titleタグやh1タグの内容を抽出し、連想配列に格納。そして、その連想配列をJSON形式にしてjqueryに返し、htmlにレンダリングしたいのですが上手くいきません。 <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript"> function site_check(){ var url = $("#url").val(); if(url=="") return; $.getJSON("test.php?url=" + encodeURIComponent(url) ,function(res){ $("#title").html(res.title); $("#h1").html(res.h1); }); } </script> </head> <body> <div class="form"> URL <input type="text" id="url" value="" style="width:300px;" onfocus="this.select()" onkeypress="if(event.keyCode==13) site_check()" /> <button onclick="site_check()" />チェック</button> </div> title:<span id="title"></span></br> h1:<span id="h1"></span> </body> test.php↓ <?php $html=mb_convert_encoding(file_get_contents($_GET['url']), 'UTF-8', 'auto'); $array = array(); $pattern = "/(?<=<title>).+?(?=<\/title>)/mis"; preg_match($pattern,$html,$array['title']); $pattern = "/(?<=<h1>).+?(?=<\/h1>)/mis"; preg_match($pattern,$html,$array['h1']); header("Content-Type: application/json; charset=UTF-8"); echo json_encode($array); ?> このコードだと、test.phpからは、[object Object]と、レスポンスが返ってきてしまいます。

    • ベストアンサー
    • PHP
  • foreach のバグでしょうか。PHP 5.3.3 で悩んだところが

    foreach のバグでしょうか。PHP 5.3.3 で悩んだところがあります。 あるレコードが正規表現にマッチした場合、そのレコードに対して何らかの処理をするスクリプトを書いていました。 しかし思ったように動かず原因を調べました。結果、配列の値が変わっていることに気づきました。  ◇テスト用レコードの内容   http://www.yahoo.co.jp/   http://www.bing.com/   http://www.goo.ne.jp/   http://www.google.co.jp   http://d.hatena.ne.jp/  ◇先頭一致して欲しい文字列   http://www.google.co.jp/   http://www.bing.com/   http://www.youtube.com/  この場合、処理の対象は2件です。  私が書いたスクリプトでは3回マッチしてしまいます。  以下、テスト用に作ったスクリプトです。 <?php // URL のパターンを用意 (とりあえず以下の3パターン) $ar = array(); $ar['Google'] = array(  'URL' => 'http://www.google.co.jp/' ); $ar['Bing'] = array(  'URL' => 'http://www.bing.com/' ); $ar['YouTube'] = array(  'URL' => 'http://www.youtube.com/' ); // 先頭一致の正規表現にする foreach($ar as $key => &$value){  $value['regex'] = '/^' . preg_quote($value['URL'], '/') . '/'; } echo("URL の パターンを出力してみる/n"); print_r($ar); // テスト用 レコード $list = array(); $list[] = 'http://www.yahoo.co.jp/'; $list[] = 'http://www.bing.com/'; // match. $list[] = 'http://www.goo.ne.jp/'; $list[] = 'http://www.google.co.jp/'; // match. $list[] = 'http://d.hatena.ne.jp/'; // マッチするのは2回のみ...のはずが for($n = 0; $n < count($list); $n ++){  foreach($ar as $key => $value){   if(preg_match($value['regex'], $list[$n], $match)) echo("match.\n");  } } echo("もう一度 URL のパターンを出力してみる\n"); print_r($ar); echo("なぜか一番最後の配列の値が変わっている。\n"); ?>

    • ベストアンサー
    • PHP