• 締切済み

preg_match_all、余計な文字を消したい

$source = "(・・・数千文字あるので省略します)" $data = '/<td class="c">\s*.*\s*<\/td>|<td>.*<\/td>/'; preg_match_all($data, $source, $data_matches); var_dump($data_matches); 上記、var_dumpの出力内容は(何故か二次元配列になってしまうんですが)、 array(1) { [0]=> array(80) { [0]=> string(72) "<td class="c"> hogehoge </td>" [1]=> string(21) "<td class="c">hogehoge</td>" [2]=> string(27) "<td>hogehoge</td>" [3]=> string(9) "<td>hogehoge</td>" [4]=> string(21) "<td class="c">hogehoge</td>" [5]=> string(9) "<td>hogehoge</td>" 上記の様に、欲しかったhogehogeの情報は取れているんですが、 <td class="c"></td>、<td></td>が邪魔です。。。 '/<td class="c">\s*.*\s*<\/td>|<td>.*<\/td>/'; 上記の正規表現は、hogehogeの場所を突き止めるのに必要だと思うんですが、 hogehogeのみ抽出したくて・・・。 $re = str_replace('<td class="c">', "", $data_matches); var_dump($re); 例えば上記の様にしても、<td class="c">が消えてくれません。。。 質問 1、何故、二次元配列になってしまうんでしょうか?問題ないのでしょうか?出来れば普通の配列にしたいんですが・・・。 2、どうすればhogehogeの場所を突き止め、そしてさらにhogehogeのみの情報を抽出出来るでしょうか?

みんなの回答

  • shimix
  • ベストアンサー率54% (865/1590)
回答No.3

うーん・・。すでに適切な回答が付いているような気もします(汗 マニュアルをちゃんと読んで書いていけば到達出来ると思うんですけどねぇ・・・ <?php $source =<<<EOD <tr> <td class="c"> <IMG border='0' src='../common/img/noimage.gif'> </td> <td class="c">hoge</td> <td>hoge</td> <td></td> <td class="c">hoge</td> <td></td> <td class="c"></td> <td class="c"><A hoge</a></td> </tr> <tr> <td class="c"> <IMG border='0' src='hoge'> </td> <td class="c">hoge</td> <td>hoge</td> <td>hoge</td> <td class="c">hoge</td> <td>hoge</td> <td class="c">hoge</td> <td class="c">hoge</td> </tr> <tr> <td class="c"> <IMG border='0' src='hoge'> </td> <td class="c">hoge</td> <td>hoge</td> <td>hogehoge</td> <td class="c">hoge</td> <td>hoge</td> <td class="c">hoge</td> <td class="c"><A target="_blank" href="hoge"><img src="../common/img/to_site.jpg" width="42" height="30"></a></td> </tr> <tr> EOD; $data = '/<td class="c">(.*)<\/td>|<td>(.*)<\/td>/'; preg_match_all($data, $source, $data_matches, PREG_PATTERN_ORDER + PREG_OFFSET_CAPTURE); $arr = $data_matches[1]; foreach ($arr as $key=>$val) { if ($val[0] === '') { continue; } print htmlspecialchars($val[0]) . '&nbsp;&nbsp;pos:' . $val[1] . '<br />' . PHP_EOL; }

すると、全ての回答が全文表示されます。
回答No.2

> 1、何故、二次元配列になってしまうんでしょうか?問題ないのでしょうか?出来れば普通の配列にしたいんですが・・・。 それは、preg_match_allの期待された動作だと思います。 http://php.net/manual/ja/function.preg-match-all.php flagsの項目を読むと、こういうことが書いてありませんか? | PREG_PATTERN_ORDER | $matches[0] はパターン全体にマッチした文字列の配列、 | $matches[1] は第 1 のキャプチャ用サブパターンにマッチした文字列の配列、 | といった順番となります。 書いておられるプログラム中ではサブパターンを使用していないので、なぜ二次元配列か理解できないかもしれません。例えば、パターンが例えば'/<td class="c">\s*(.*)\s*<\/td>/'と()を使ってみるとサブパターンのところだけを取り出した配列ができるのでこれの必然性というのが少しは理解できると思います。 サブパターンとは?: http://php.net/manual/ja/regexp.reference.subpatterns.php 2次元配列から欲しい方の1次元配列を取り出せば良いと思います。 > 2、どうすればhogehogeの場所を突き止め、そしてさらにhogehogeのみの情報を抽出出来るでしょうか? 自分は質問文の次の文が何を主張しているのかよくわからなかったのですが、次のどちらかでしょうか。 > <td class="c"></td>、<td></td>が邪魔です a. <td></td>で囲っているのが邪魔。<td>foo</td>ではなく、fooと表示してほしい。 b. <td></td>と中身が入っていないものがマッチするのが邪魔。中身が無いものは消してほしい。 a.の場合はこんなパターンを書くと良いでしょう。 '/<td class="c">\s*(.*)\s*<\/td>|<td>(.*)<\/td>/' そして、できた2次元配列からそこだけ取り出します。 $pattern = '/<td class="c">\s*(.*)\s*<\/td>|<td>(.*)<\/td>/'; preg_match_all($pattern, $source, $matches, PREG_PATTERN_ORDER); $extracted = $matches[1]; var_dump($extracted); b.だとすると、パターンを改良することをおすすめします。 '/<td class="c">\s*.+\s*<\/td>|<td>.+<\/td>/' *だと0文字でもマッチするので、+にして1文字以上のときにマッチするようにしましょう。 aとbの両方の場合はこんな感じでしょうか。 $pattern = '/<td\s*(|class="c")>\s*(.+)\s*<\/td>/'; preg_match_all($pattern, $source, $matches, PREG_PATTERN_ORDER); $extracted = $matches[2]; var_dump($extracted); 正規表現のパターンで同じ事を二度書くのは嫌ですし、サブパターンを書く所でミスってしまいそうなのでちょっと整理しました。

すると、全ての回答が全文表示されます。
  • agunuz
  • ベストアンサー率65% (288/438)
回答No.1

#知恵袋の続きですね(汗 http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q14103000684 結局、私が提示した(Uを付加した) $data = '/<td class="c">\s*.*\s*<\/td>|<td>.*<\/td>/U'; と変えてもダメだったのでしょうか? >$source = "(・・・数千文字あるので省略します)" 数千文字を転記しろというのは無理だとわかりますが「現象が再現できる」文字列を提示できませんか?こちらで再現できないものは調べようがありません。 >1、何故、二次元配列になってしまうんでしょうか? については、同じ回答しかしません。必ず一読してください。これを読まずに質問されても困りますので。 RTFM. http://php.net/manual/ja/function.preg-match-all.php >どうすればhogehogeの場所を突き止め、 RTFM. http://php.net/manual/ja/function.preg-match-all.php ヒント)PREG_OFFSET_CAPTURE

htryhjykjkyu
質問者

補足

>>$data = '/<td class="c">\s*.*\s*<\/td>|<td>.*<\/td>/U'; 結果のソースも見ましたが変わりませんでした。 >>数千文字を転記しろというのは無理だとわかりますが「現象が再現できる」文字列を提示できませんか?こちらで再現できないものは調べようがありません。 <tr> <td class="c"> <IMG border='0' src='../common/img/noimage.gif'> </td> <td class="c">hoge</td> <td>hoge</td> <td></td> <td class="c">hoge</td> <td></td> <td class="c"></td> <td class="c"><A hoge</a></td> </tr> <tr> <td class="c"> <IMG border='0' src='hoge'> </td> <td class="c">hoge</td> <td>hoge</td> <td>hoge</td> <td class="c">hoge</td> <td>hoge</td> <td class="c">hoge</td> <td class="c">hoge</td> </tr> <tr> <td class="c"> <IMG border='0' src='hoge'> </td> <td class="c">hoge</td> <td>hoge</td> <td>hogehoge</td> <td class="c">hoge</td> <td>hoge</td> <td class="c">hoge</td> <td class="c"><A target="_blank" href="hoge"><img src="../common/img/to_site.jpg" width="42" height="30"></a></td> </tr> <tr> .... ... .. .

すると、全ての回答が全文表示されます。

専門家に質問してみよう