如何包装尚未包装的单词或单词序列?

时间:2010-10-13 13:01:54

标签: php regex word text-analysis

我正在尝试用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的
  • 坐下来
  • SED
  • sed enim

我想导致:

  

-Lorem - -ipsum - dolor -sit amet - ,   奉献精神。 Phasellus   rhoncus venenatis orci sed porta。桑达   非dolor色情。马塞德赛马场    -sit amet - nulla egestas facilisis。信用评级机构   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 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 fames ac turpis egestas。   Suspendisse id est velit,eu cursus   华富嘉洛。 Vivamus lacinia euismod pretium。

有什么想法吗?

2 个答案:

答案 0 :(得分: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');
}

答案 1 :(得分: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;
}