-4

私はこの正規表現を持っています:

preg_match_all("/<\s*?img\s[^>]*?src=([\"']??)([^\"' >]*?)\1[^>]*?>/si", $content, $m);

アイデアは、HTML の一部ですべての画像リンクを見つけることです。このコンテンツを考えると:

<p>
    <img alt="" src="/emailimg/interdigital_old.jpg" style="width: 377px; height: 245px; " />Some text here.</p><a href="site.html">test</a>

正規表現を実行した後、 $m は3つの空の配列を持つ配列ですが、このサイトでテストすると、結果は次のようになります:

Array
(
    [0] => Array
        (
            [0] => <img alt="" src="/emailimg/interdigital_old.jpg" style="width: 377px; height: 245px; " />
        )

    [1] => Array
        (
            [0] => "
        )

    [2] => Array
        (
            [0] => /emailimg/interdigital_old.jpg
        )

)

どうしたの?構成の問題ですか?

4

1 に答える 1

4

DOM / XPath (つまり正しい) 方法:

<?php

  $html = '
<p>
    <img alt="" src="/emailimg/interdigital_old.jpg" style="width: 377px; height: 245px; " />Some text here.</p><a href="site.html">test</a>
';

  $dom = new DOMDocument('1.0');
  $dom->loadHTML($html);

  $xpath = new DOMXPath($dom);

  $links = array();
  foreach ($xpath->query('//img/@src') as $img) $links[] = $img->value;
  print_r($links);

テスト済みで動作しています。

編集

正規表現が機能しない理由は 2 つあります。

  1. 二重引用符で囲まれた文字列を使用して正規表現を宣言しました。二重引用符で囲まれた文字列は、PCRE に渡されるに、特定のエスケープ シーケンス自体を補間するため、これは予期しない結果になることが多く、完全には明らかではありません。これがあなたのケースで引き起こした問題は\1、8進数の文字定義(ここで定義されているように)として解釈されていたため、 PCREで使用する文字列ではなく、式にリテラル0x01(見出しの開始)文字が含まれていたことです。\1後方参照。

    このような問題が発生した場合、最初echoに式を単純にスクリーニングして、スクリプトで宣言した文字列が PHP によってどのように補間されるかを確認することから始めるとよいでしょう。ここその特定の問題のデモンストレーションです。

  2. ([\"']??)- 2 番目のクエスチョン マークはそれを破っています。あなたがこれで何を達成しようとしていたのか、実際にはよくわかりませんが、それは単なるタイプミスでしたか? PCRE がこれをどのように解釈しているのか、なぜそれが壊れているのかを正確に理解するのに少し苦労していますが、そうであると言うだけで十分です。FTR、それが持つ効果は、式が引き続き<img>タグに一致することですが、次のキャプチャ グループ (実際に必要なデータ) は空です。

それでは、正規表現を分解して、どのように改善できるかを見てみましょう。

  • <\s*?img-*ここで貪欲でないことは無意味です。\s空白のみに一致し、次のシーケンスはアルファになるため、単純<\s*imgに十分です。HTML タグの冒頭とタグ名の間に先頭の空白を使用できるかどうかは実際に<はわかりませんが、適切なパーサーはおそらくそうするので、許可しても害はないと思います。
  • \s[^>]*?src=(["']??)- 前述のよう??に、キャプチャ グループの は式を壊しており、そもそも何をしようとしていたのかわかりません。*また、タグは で終わるため、貪欲でないことは無意味だと思います。最後まで>見つからない場合はsrc、とにかく一致しません。さらに、許可すべきではない場所で空白を許可しているが、パーサーが許可する可能性がある場合は、おそらく=. これを に書き換え\s[^>]*src\s*=\s*(["']?)ます。
  • ([^"' >]*?)\1- 引用符で囲まれていない属性を処理できるかどうかを懸念していると仮定すると、ここで不満はありません。もちろん、属性が常に引用されることわかっている場合は、使用中の引用タイプを決定した前のキャプチャ グループから を使用([^\1]*?)\1してドロップするだけで済みます。?
  • [^>]*?>-ここに苦情はありません。
  • /si-式のどこにも ssがないため、修飾子は無意味です。.害はありませんが、助けにもならないので、不要です。

したがって、これらすべてをまとめると、次のように正規表現を記述します。

/<\s*img\s[^>]*src\s*=\s*(["']?)([^"' >]*?)\1[^>]*>/i

...引用符を適切にエスケープして PHP 文字列宣言に変換すると、次のようになります。

$expr = '/<\s*img\s[^>]*src\s*=\s*(["\']?)([^"\' >]*?)\1[^>]*>/i';

...ちなみに、これはうまく機能します。

今でも、追加のコードを考慮しても DOM メソッドの方が優れていると主張しています。これは、私の正規表現スキルが忘れていたエッジ ケースをおそらくキャッチするからです。確かに、正規表現はやや高速に見えますが。

于 2012-06-08T12:43:07.770 に答える