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);
    }

从此关键字列表中:

  • 洛雷姆
  • ipsum
  • 坐下
  • 空值
  • sed
  • sed enim

我想导致:

-Lorem- -ipsum- dolor -sit amet- , consectetur adipiscing elit。Phasellus rhoncus venenatis orci sed porta。Sed 非悲伤爱欲。Suspendisse a massa -sit amet- nulla egestas facilisis。Cras fringilla、leo ac ullamcorper semper、urna eros pretium lectus、nec rhoncus ligula risus eu velit。Nulla eu dapibus magna。Sed vehicula tristique lacinia。Maecenas tincidunt metus 在 urna consequat nec congue libero iaculis。Nulla facilisi。Phasellus -sedsem 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 回答