3

の使用について少し混乱していますpreg_replace_callback()

内に$contentいくつかの URL を含む があります。

以前私が使用した

 $content = preg_match_all( '/(http[s]?:[^\s]*)/i', $content, $links );


 foreach ($links[1] as $link ) {
            // we have the link. find image , download, replace the content with image
            // echo '</br>LINK : '. $link;
            $url = esc_url_raw( $link );
            $url_name = parse_url($url); 
            $url_name = $description = $url_name['host'];// get rid of http://..
            $url = 'http://somescriptonsite/v1/' .  urlencode($url)   . '?w=' . $width ;
            } 

    return $url;

しかし、本当に必要なのは、元の URL を解析した URL に置き換えることです...

だから私はpreg_replace_callbackを試しました:

function o99_simple_parse($content){

$content = preg_replace_callback( '/(http[s]?:[^\s]*)/i', 'o99_simple_callback', $content );


return $content;
}

と :

function o99_simple_callback($url){
    // how to get the URL which is actually the match? and width ??
        $url = esc_url_raw( $link );
        $url_name = parse_url($url); 
        $url_name = $description = $url_name['host'];// get rid of http://..
        $url = 'http://something' .  urlencode($url)   . '?w=' . $width ; 
        return $url; // what i really need to replace 
    }

$url私は、コールバックは、すべての一致がコールバックを呼び出して (再帰的に?) 結果を取得するように動作し、その結果、$content 内の URL を解析された fromにオンザフライで置き換えることができると想定しましたo99_simple_callbac()

しかし、ここでの別の質問(特にこのコメント) が私の疑問を引き起こしました。

実際に一致の配列全体を渡す場合、以前に使用したもの (最初の例) とコールバックの例のpreg_replace_callback()実際の違いは何ですか?preg_match_all()

私は何が欠けている/誤解していますか?? $contentで見つかった URLを解析された URL に置き換える正しい方法は何でしょうか?

4

3 に答える 3

4

他の答えで十分だったかもしれませんが、もっと簡単な例を使ってもう 1 つ考えさせてください。

に次のデータがあるとします$subject

RECORD Male 1987-11-29 New York
RECORD Female 1987-07-13 Tennessee
RECORD Female 1990-04-14 New York

および の次の正規表現$pattern

/RECORD (Male|Female) (\d\d\d\d)-(\d\d)-(\d\d) ([\w ]+)/

3つのアプローチを比較してみましょう。

preg_match_all

まず、バニラpreg_match_all:

preg_match_all($pattern, $subject, $matches);

これが次の$matchesようになります。

Array
(
    [0] => Array
        (
            [0] => RECORD Male 1987-11-29 New York
            [1] => RECORD Female 1987-07-13 Tennessee
            [2] => RECORD Female 1990-04-14 New York
        )

    [1] => Array
        (
            [0] => Male
            [1] => Female
            [2] => Female
        )

    [2] => Array
        (
            [0] => 1987
            [1] => 1987
            [2] => 1990
        )

    [3] => Array
        (
            [0] => 11
            [1] => 07
            [2] => 04
        )

    [4] => Array
        (
            [0] => 29
            [1] => 13
            [2] => 14
        )

    [5] => Array
        (
            [0] => New York
            [1] => Tennessee
            [2] => New York
        )

)

私の例の性別フィールドとあなたの例の URL フィールドについて話しているかどうかにかかわらず、ループを介してそのフィールドだけ$matches[1]を反復処理することは明らかです。

foreach ($matches[1] as $match)
{
    $gender = $match;
    // ...
}

ただし、お気付きのように、 に加えた変更は、$matches[1]そのサブ配列を参照によって反復処理したとしても、 に反映されません。つまり$subject、を介して置換を実行することはできません。preg_match_all

PREG_SET_ORDER を使用した preg_match_all

その前に、の一般的に使用されるフラグのpreg_replace_callback1 つを見てみましょう。preg_match_allPREG_SET_ORDER

preg_match_all($pattern, $subject, $matches, PREG_SET_ORDER);

これは(一見)まったく異なるものを出力します!

Array
(
    [0] => Array
        (
            [0] => RECORD Male 1987-11-29 New York
            [1] => Male
            [2] => 1987
            [3] => 11
            [4] => 29
            [5] => New York
        )

    [1] => Array
        (
            [0] => RECORD Female 1987-07-13 Tennessee
            [1] => Female
            [2] => 1987
            [3] => 07
            [4] => 13
            [5] => Tennessee
        )

    [2] => Array
        (
            [0] => RECORD Female 1990-04-14 New York
            [1] => Female
            [2] => 1990
            [3] => 04
            [4] => 14
            [5] => New York
        )

)

これで、各サブ配列には、キャプチャ グループごとのマッチのセットではなく、マッチごとのキャプチャグループのセットが含まれます。(さらに言い換えると、これは他の配列の転置です。) 各一致の性別 (または URL) を操作したい場合は、次のように記述する必要があります。

foreach ($matches as $match)
{
    $gender = $match[1];
    // ...
}

preg_replace_callback

と、preg_replace_callbackこんな感じです。フラグを使用しているかのように、一致の各セット(つまり、すべてのキャプチャ グループを一度に含む)に対してコールバックを呼び出します。PREG_SET_ORDERつまり、preg_replace_callback使用方法を対比し、

preg_replace_callback($pattern, $subject, 'my_callback');
function my_callback($matches)
{
    $gender = $match[1];
    // ...
    return $gender;
}

例にPREG_SET_ORDER。2 つの例がまったく同じ方法で一致を反復する方法に注意してください。唯一の違いはpreg_replace_callback、置換のために値を返す機会を与えることです。

于 2013-03-28T14:57:29.323 に答える
3

すべての一致を渡すわけではありませんが、一致ごとにコールバックを呼び出します。コールバックは単一の文字列パラメーターを受け取るのではなく、文字列のリストを受け取ります。$match[0]一致全体であり$match[1]、最初のキャプチャ グループ (最初の括弧の間の正規表現の内容) です。

したがって、コールバックは次のようになります。

function o99_simple_callback($match){
    $url = $match[1];
    //$url = esc_url_raw( $link );
    $url_name = parse_url($url); 
    $url_name = $description = $url_name['host'];// get rid of http://..
    $url = 'http://something' .  urlencode($url)   . '?w=' . $width ; 
    return $url; // what i really need to replace 
}

のマニュアルの例も参照してください。preg_replace_callback

于 2013-03-28T03:03:05.497 に答える
2

preg_replace_callback

  1. preg_replace_callback() を使用してパターンを置き換える
  2. コールバック関数による置換文字列の生成
  3. 無名関数で置換文字列を生成する
于 2013-03-28T03:00:15.070 に答える