preg_matchの検索について

このQ&Aのポイント
  • preg_matchを使用して正規表現の検索を行いました。
  • 検索結果には配列が返され、[0]にはマッチした全体の文字列が、[1]にはマッチした部分文字列が格納されます。
  • つまり、[1]は正規表現パターン内の括弧で囲まれた部分にマッチした部分文字列を示しています。
回答を見る
  • ベストアンサー

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
  • 回答数2
  • ありがとう数2

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

  • ベストアンサー
  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.2

0番目の要素はマッチした文字列 1番目の要素はカッコで囲まれた1個目の要素 最短マッチなら「.*?」で十分 <?PHP $pat = '/<a href=".*?">/'; $html="<p><a href=\"http://test.net/test3.html\">リンク</a></p>"; preg_match($pat,$html,$match); print_r($match); ?>

ShiftTail
質問者

お礼

ありがとうございます。 0番目の要素はマッチした文字列 1番目の要素はカッコで囲まれた1個目の要素 そういうことだったのですね。 すっきりしました。

その他の回答 (1)

回答No.1

$pat = '/<a href="[^"]*">/'; $html="<p><a href=\"http://test.net/test3.html\">リンク</a></p>"; preg_match($pat,$html,$match); print_r($match); 検証してみなされ。

ShiftTail
質問者

お礼

検証してみたところ 正しき結果がでました。 ありがとうございました。

関連するQ&A

  • preg_match_allで取得データをDBへ

    質問:preg_match_allで取得したデータをDBへ格納したいです。 記述文 $pattern = "|HREF=.*?\>|"; preg_match_all($pattern,$str,$match); 補足: $pattern で指定範囲を書いてます。 $str には $patternでとってくる参照データ先が入ってきます。 print_r($match); で念のためブラウザに吐き出すと Array ( [0] => Array ( [0] => HREF="AAA"> [1] => HREF="../../../../Top"> 以下省略 取得したい範囲が取れていることは確認できました。 目的は、とってきた [0] => HREF="AAA"> [1] => HREF="../../../../Top"> : =>より先の文字列が、DBの1つのレコードに1つずつ入っていくイメージです。 アドバイスよろしくお願いします。

    • ベストアンサー
    • PHP
  • preg_matchの正規表現がうまくいかない

    たとえば、http://gehasoku.com/?p=2のソースコードには ------------------- <rdf:Description rdf:about="http://www.com/aaa.html" trackback:ping="http://www.com" dc:title="タイトル" dc:identifier="http://iii.com/bbb.html" dc:subject="ハードウェア" dc:description="1 名前:名無しさん " dc:creator="soft_net" dc:date="2012-02-21T20:05:01+09:00" /> ------------------- のような形の<rdf:Description~~~/>タグの情報ががいくつかあると思います。これらすべてを文字列として取得したくて、次のようなphpを作成しましたが、うまく動作しません。 原因はどうやらpreg_match_allの正規表現がうまくいっていないからのようですので、 <rdf:Description~~~/>を抜き出すことができる正規表現を教えてください。 自分でもここでチェックしながらやりましたが、 http://www.rider-n.sakura.ne.jp/regexp/regexp.php <rdf:Description~をマッチすることはできても、/>で閉じることができませんでした。 よろしくお願いします。 <?php $url="http://gehasoku.com/?p=2"; $html=file_get_contents($urls); preg_match_all("/<rdf:Description(.*)?\/>/",$html,$match); print_r($match); foreach($match[1] as $value){ echo $value; } ?>

    • ベストアンサー
    • PHP
  • preg_matchのキャプチャ用サブパターンにマッチした文字列について

    お世話になります preg_matchのキャプチャ用サブパターンにマッチした文字列について 意図した動作が、試行錯誤しても全く得られませんので 分かる方にお教えいただきたく存じます 条件1 [*DATA: *]で囲まれたデータ(以下DATA)を取得 条件2 DATAにはoXoまたはoYoが順不同で、それぞれ1回または0回出現する $test = '[*DATA: A oYo B oXo C *]'; $reg = '/\[\*DATA:(.*?)(oXo|oYo)(.*?)(oXo|oYo)?(.*?)\*\]/u'; preg_match($reg,$test,$match); $matchの結果 $match[0] => [*DATA: A xYx B xXx C *] $match[1] => A $match[2] => oYo $match[3] => $match[4] => $match[5] => B oXo C 期待した結果 $match[0] => [*DATA: A oYo B oXo C *] $match[1] => A $match[2] => oYo $match[3] => B $match[4] => oXo $match[5] => C 1回または0回を表す「(oXo|oYo)?」が「0回」という条件が先に評価されてしまっているようなのですが「1回」を先にするすべはあるのでしょうか? 「(oXo|oYo)?」を「(oXo|oYo)」にすると期待した結果になりますが、条件2の「oXoが0回」「oYoが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_match_all 

    $c = preg_match_all('@href="/Top/World/Japanese/(?P<query>.*?)">(?:<b>|)(?P<cate>.*?)(?:</b>|)</a>@s', $buf,$match,PREG_SET_ORDER); print_r($match); の(?:<b>|)と(?:</b>|)の部分がまちがっているので、<b></b>タグがあってもなくてもいい場合にマッチさせることができないと思っています。 どうか教えてくださいませ。 ちなみにPHPの5.2.2です。

    • ベストアンサー
    • 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
  • 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
  • PHP:preg_match_allで複数条件指定

    preg_match_allで複数条件を設定する方法についてお尋ねします。 環境 PHP:5.1.6 MySQL:5.0.77 --------ソース例------------------------------------------ <a href="1000/23">1: 【国語】接続後について (授業1) (20)</a> <a href="1000/26">2: 【数学】分数 (206)</a> --------------------------------------------------------- 上記のようなHTMLソースを分解してMySQLに登録することを考えています。 (1行目) 1000/23 | 1 | 【国語】接続後について (授業1) | 20 (2行目) 1000/26 | 2 | 【数学】分数 | 206 という形に a hrefの中身 |スレッド番号 | タイトル | コメント数 4つに分解してMySQLに登録します。 正規表現を学んで、個別にデータを取り出すことはできました。 以下に作成したソースを記載します。 $contents='<a href="1000/23">1: 【国語】接続後について (授業1) (20)</a><a href="1000/26">2: 【数学】分数 (206)</a>'; preg_match_all( '/<a href="(.*?)">/su', $contents, $match ); foreach ( $match[ 1 ] as $var ) { echo htmlspecialchars($var)."<br>"; } preg_match_all( '/">([0-9]*?):/su', $contents, $match2 ); foreach ( $match2[ 1 ] as $var2 ) { echo htmlspecialchars($var2)."■<br>"; } preg_match_all( '/[0-9]: (.*?)\([0-9]*\)<\/a>/su', $contents, $match3 ); foreach ( $match3[ 1 ] as $var3 ) { echo htmlspecialchars($var3)."■<br>"; } preg_match_all( '/\(([0-9]*?)\)</su', $contents, $match4 ); foreach ( $match4[ 1 ] as $var4 ) { echo htmlspecialchars($var4)."●<br>"; } 【実行結果】 1000/23 1000/26 1 2 【国語】接続後について (授業1) 【数学】分数 20 206 1行ずつMySQLに登録したいので preg_match_all( '/条件1,条件2,条件3,条件4/su', $contents, $match ); のような形で指定して個々の値を下記の変数に入れることは可能でしょうか? ループ処理開始{ $url $num $title $res //MySQLに接続 //データ登録 }

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

    初級者です。 初歩的な質問で申し訳ないですが質問させていただきます。 データベースのテーブルにある日付にマッチすれば"マッチ"、マッチしなければ"マッチなし"と表示させたく思っております。 ~DB内任意のフォームデータ~ 0405 0406 0407 ・ ・ ~~~~~~~~~~~~~~ そこで下記のスクリプトを作ったのですが、 この方法だとDBに登録されている日付の分だけ "マッチ" "マッチなし" ・ ・ と表示されてしまします。 ==test.php== <? //$keydayはリクエストのあった日付Ymd形式 //getRecList()に関しては別ファイルにてfunction済み //["日付"]というのは上記DBの日付の項目名 $reclist = getRecList(); foreach ($reclist as $rec) { $matchday = (date_format("Ymd",$rec["日付"])); unset($found); $found[0]=1; $matchecho ="マッチ"; $unmatchecho="マッチなし"; ?> <? if (preg_match("/$keyday/",$matchday)) { ?>  <? if (!array_key_exists($matchecho,$found)) { ?>   <? echo $matchecho ?><? $found[$matchecho] = 1; ?>  <? } ?> <? } else { ?>  <? if (!array_key_exists($unmatchecho,$found)) { ?>   <? echo $unmatchecho ?><? $found[$unmatchecho] = 1; ?>  <? } ?> <? } ?> <? } ?> ?> ======== やりたい事は、 DBに登録されている日付の数に左右されずマッチする日付があったら1回だけ"マッチ"と表示、 待ちしなければ1回だけ"マッチなし"と表示させたいのです。 ・・なんかforeachで回している事自体が間違いな気がしますが、どうかよろしくお願いいたします。

    • 締切済み
    • PHP
  • preg_match・ereg_replaceの動作について

    preg_matchとereg_matchの動作について調べています。 下記のスクリプトを実行すると、$stringが「代入テスト」となります。 ------------------------------------------- $v_insert = "代入" $string = "{%v_insert}テスト"; while (preg_match("/\{%(.*)\}/U", $string, $match)){ $string = ereg_replace($match[0], $$match[1], $a_subject); } ------------------------------------------- $$match[1]→$($match[1])→$(v_insert)となり、 $match[0]→/\{%(.*)\}/U $match[1]→v_insert $$match[1]→代入 となるのは分かったんですが、なぜ、$match[0]→/\{%(.*)\}/Uで$match[1]がv_insertになるのかが分かりません。 このスクリプトはどのように動き、どのように変数に値が設定されているのでしょうか。

    • ベストアンサー
    • PHP

専門家に質問してみよう