0

preg_replace を使用して、特定のリストから単語と単語のシーケンスをラップしようとしています。ほとんど機能しますが、機能しないユースケースがいくつかあり、その方法がわかりません。

たとえば、私はこれを行います:

    // sort by descending length
    usort($this->_keywords, function($a,$b){return(strlen($a)<strlen($b));});

    // wrapper is -%string%-
    foreach ($this->_keywords as $keyword) {
        $value = preg_replace('/((?!-)' . $keyword . '(?!-))/i', str_replace('%string%', '\1', $this->_wrapper), $value);
    }

このキーワード リストから:

  • ロレム
  • イプサム
  • 座って
  • ヌル
  • シード
  • セド・エニム

私は次のようになりたい:

-Lorem- -ipsum- dolor -sit amet- , consectetur adipiscing elit. Phasellus rhoncus venenatis orci sed porta. セド ノン ドロール エロス。massa を中断する - 座る amet- nulla egestas facilisis. Cras fringilla、leo ac ullamcorper semper、urna eros pretium lectus、nec rhoncus ligula risus eu velit。Nulla eu dapibus マグナ。Sed vehicula tristique lacinia。Maecenas tincidunt metus at urna consequat nec congue libero iaculis. Nulla facilisi。Phasellus -sed- sem ut risus mattis accumsan eu -sed enim- . Pellentesque 居住者 morbi tristique senectus et netus et malesuada 名声 ac turpis egestas. Suspendisse id est velit, eu cursus quam. Vivamus lacinia euismod pretium。

何か案は?

4

2 に答える 2

1

最も簡単なのは、 を使用しpreg_replace_callback()て、既にラップされている単語と各キーワードに一致させることです。一致がラップされた単語の場合は、変更せずにそのまま返します。問題のあるルックアラウンドは必要ありません。

function compare_length($a, $b) {
    return strlen($a) < strlen($b);
}

function build_regex($keywords) {
    usort($keywords, 'compare_length');
    $pieces []= '/(?<wrapped>-[\w\s]*-)|(?<keyword>';
    for ($i = 0; $i < count($pieces); $i++) {
        if ($i > 0) $pieces []= '|';
        $pieces []= preg_quote($keywords[$i], '/');
    }
    $pieces []= ')/';
    return implode("", $pieces);
}

function wrap_callback($match) {
    if (!empty($match['wrapped'])) {
        return $match['wrapped'];
    }
    return "-{$match['wrapped']}-";
}

function wrap($text, $keywords) {
    $regex = build_regex($keywords);
    return preg_replace_callback($regex, 'wrap_callback');
}
于 2010-10-13T13:37:16.277 に答える
0

最終的\bに、単語境界に対応するメタ文字を使用して問題を解決しました。

public function filter($value)
{
    usort($this->_keywords, function($a,$b){return(strlen($a)<strlen($b));});

    foreach ($this->_keywords as $keyword) {
        $value = preg_replace(
            '/((?<!-)('.$keyword.'\b)(?!\-))/i',
            str_replace('%string%', '\2', $this->_wrapper) . '\3',
            $value
        );
    }

    return $value;
}
于 2010-10-15T11:31:48.703 に答える