1

preg_replace_callback を使用して巨大なカタログ製品の説明の SEO を行っていますが、正規表現に問題があります。

これらの単語 (帽子、シャツ) をすべて置き換えたいのですが、"men's" の後の単語 + その間の 0-2 単語、たとえば "men's pretty black hat"、"men's long shirt" は置き換えないでください。

これがデバッグコードです。実際のアプリケーションでは、コールバックを使用して各単語の適切な置換を選択します。

$str = "men's black hat, and orange shirt!";
preg_match_all('/((\s|\.\s|,\s|\!\s|\?\s)(hat|shirt)(\s|\.|\.\s|,\s|\!|\!\s|\?|\?\s))/i', $str, &$_matches);
print_r($_matches);

ありがとう

4

2 に答える 2

0

後読みは固定長でなければならないため、この問題を攻撃する方法は機能しません。

IMHOあなたはやりすぎようとしてpreg_relace_callbackいます。特定のレベルを超えて複雑な操作を実行したい場合は、単一の関数呼び出しの利便性を犠牲にするのが合理的です。問題を攻撃する別の方法を次に示します。

  1. 各単語が元のテキストのどこに表示されるかがわかるようpreg_splitに、フラグとともにテキストを単語に分割するために使用します。PREG_SPLIT_OFFSET_CAPTURE
  2. 単語の配列を反復処理します。配列に対して「否定後読み」を実行して、帽子やシャツの前に興味のある他の用語のいずれかがあるかどうかを確認するのが非常に簡単になりました。
  3. 帽子やシャツの正の一致が見つかった場合は常に、正の一致のオフセットpreg_splitと (既知の) 長さを使用substr_replaceして、元のテキスト入力をオンにします。

例えば:

$str = "men's black hat, and orange shirt!";
$targets = array('hat', 'shirt');
$shield = 'men\'s';
$bias = 0;

for ($i = 0; $i < count($words); ++$i) {
    list ($word, $offset) = $words[$i];

    if (!in_array($word, $targets)) {
        continue;
    }

    for ($j = max($i - 2, 0); $j < $i; ++$j) {
        if ($words[$j][0] === $shield) {
            continue 2;
        }
    }

    $replacement = 'FOO';
    $str = substr_replace($str, $replacement, $offset + $bias, strlen($word));
    $bias += strlen($replacement) - strlen($word);
}

echo $str;

実際に見てください

于 2013-08-26T16:10:28.937 に答える