• ベストアンサー

最短一致の使い方

最短一致の使い方がよくわりません。 $str = "<div><div><p>ABC</p></div><div><p>DEF</p></div></div>"; $str =~ /<div.*?ABC.*?<\/div>/; print $&; 「<div><p>ABC</p></div>」となると考えていたのですが、 「<div><div><p>ABC</p></div>」と表示されます。 正規表現をどのようにしたら期待通りの結果を得られますでしょうか? 前半の最短一致がダメで後半の最短一致がOKという理由もできたら教えて下さい。

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

  • ベストアンサー
  • poppo64
  • ベストアンサー率57% (11/19)
回答No.4

自分も気になったので追求してみました。 「一番内側の<div>~</div>」に一致、ということなら下記の方が確実かもしれません。試験はしましたがちょっと自信はありません。 $str =~ m{<div\b[^>]*?>([^<]*|<(?!div)\b[^>]*>)*ABC.*?</div>};

luka3
質問者

お礼

つきつめるとどんどん長くなっていくのですね。 奥が深いです。

その他の回答 (3)

  • poppo64
  • ベストアンサー率57% (11/19)
回答No.3

$str =~ m{<div>(?!<div).*ABC.*?</div>}; Perlの正規表現は先頭から照合していくので、始めに1つ目の"<div"にマッチし、その後".*?"を照合しようとするので2つ目の"<div"も含まれてしまいます。 後半も同じように先頭から処理していきますので最初の"</div>"で照合が終わります。 例示した正規表現は(?!●●)とすることで「●●が後に続かない<div>」という指定になります。 質問例の正規表現が"<div"となっているのは、おそらく属性がある場合を考慮してのことだと思いますが、下記のようにすると希望の結果が得られると思います。 $str = "<div class='first'><div class='second'><p>ABC</p></div><div><p>DEF</p></div></div>"; $str =~ m{<div\b[^>]*?>(?!<div\b).*ABC.*?</div>}; print $&; # <div class='second'><p>ABC</p></div>

参考URL:
http://fleur.hio.jp/perldoc/mix/pod/perlre.mix.html#Extended_Patterns
luka3
質問者

お礼

>おそらく属性がある場合を考慮してのことだと思いますが というところまで読み取っていただいて感謝します。 拡張パターンを使えばいいのですね。 (逆にいうと通常の正規表現ではできないということ?) 希望通りの結果を得ることができて満足です。 ありがとうございました。

  • kumoz
  • ベストアンサー率64% (120/185)
回答No.2

すみません。正規表現の部分が間違っていました。訂正します。 $str =~ /<div[^v]*?ABC.*?<\/div>/;

  • kumoz
  • ベストアンサー率64% (120/185)
回答No.1

>前半の最短一致がダメで後半の最短一致がOKという理由もできたら教えて下さい。 正規表現では、「最長・最短」よりも「最左」が優先されます。質問の例では、文字列の 先頭からマッチを試みると成功するのでそのような結果になります。 >正規表現をどのようにしたら期待通りの結果を得られますでしょうか? あまり洗練されていませんが、. の代わりに div の1文字を除外する方法です。 $str =~ /<div[^v]*?ABC.*?</div>;

luka3
質問者

お礼

>正規表現では、「最長・最短」よりも「最左」が優先されます。 というのは知りませんでした。 理由がわかってよかったです。 ありがとうございました。

関連するQ&A