正規表現でわからなくて困ってます(PHP)


<div>あああああ</div>いいいいい<div>うううう</div>ええええ<div>おおおお</div>

というテキストがあって
「<div>おおおお</div>」
を取って
最終的には
「<div>あああああ</div>いいいいい<div>うううう</div>ええええ」
としたいのですが、、

$r = preg_replace("/<div>.*?</div>$/u", "", $string);

最初これでいけるかなと思ったら
これだと先頭から末尾までマッチしちゃって$rがブランクに。。

どうやったら良いでしょうか

回答の条件
  • 1人1回まで
  • 13歳以上
  • 登録:2015/03/27 10:19:12
  • 終了:2015/03/27 14:59:03

ベストアンサー

id:a-kuma3 No.1

a-kuma3回答回数4524ベストアンサー獲得回数18802015/03/27 11:44:56

ポイント200pt

試してみましたけど、最短マッチの .*? がうまく効かないみたいですね。
こんな感じで後方参照を使うと、質問に書かれた例では期待してる結果にはなりますけど。

<?php
    ...
    $r = preg_replace('/(.*)<div>.*<\/div>$/', "$1", $string);
?>

因みに、質問に書かれた正規表現だと </div> の / は、エスケープしないとワーニングが出てるはずです。

他1件のコメントを見る
id:a-kuma3

回答で書いた方は、最初の .* が極力長い文字列にマッチするので、正規表現中の </div> は、文字列の中の一番最後の方にあるものにマッチします。

.*? は、最短一致なのでうまくいきそうな気もするけど .* が強いんだろうなあ...

追加で、後方参照を使わないパターンをひとつ。

<?php
    ...
    $r = preg_replace('/<(?!.*<div>).*/u', "", $string);
?>
2015/03/27 14:32:31
id:spacewarp

「最初の .* が極力長い文字列にマッチする」んですね~。
そう考えると納得が行きます。

追加のパターンもありがとうございます。参考にさせていただきます。

2015/03/27 14:58:49
  • id:TransFreeBSD
    .*が強いんじゃなくて、左側が強いんです。
    最短マッチは一番短くなるマッチを能動的に探すわけではなく、短い方から試してマッチしたらそこで終了です。
    最初のdivにマッチしたら0文字で試して1文字で試して……と、最後にマッチして終了。そこからさらに短くなるかは試さない。
  • id:a-kuma3
    >最短マッチは一番短くなるマッチを能動的に探すわけではなく、短い方から試してマッチしたらそこで終了です。
    その辺りは、何となく分かってるつもりです。

    <div>.*?</div> だと、<div>あああああ</div> にマッチするのは分かりやすいです。
    <div>おおおお</div>$ も、普通に使う正規表現です。
    <div>.*?</div>$ が、なんで <div>おおおお</div> にマッチしないかなー、と。
  • id:a-kuma3
    いや、.*? と $ の相性が悪い(あくまでも、ぼくのとらえ方)のかな。
  • id:a-kuma3
    最初にマッチしたら終了、か(TransFreeBSD さんが書いたままだけど)。
    却って、追加で書いた否定的前方一致の方が訳が分からないな (´・ω・`)

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません