2010-10-13 180 views
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
  • 存有
  • 坐阿梅德
  • sed的
  • SED enim

我想导致:

-Lorem--ipsum--sit amet-, consectetur adipiscing ELIT。 Phasellus rhoncus venenatis orci sed porta。 Sed non dolor爱神。 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 -sed- sem ut risus mattis accumsan eu -sed enim-。 Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas。关于这个问题, Vivamus lacinia euismod pretium。

任何想法?

+0

你有什么具体问题? – Roadie57 2010-10-13 13:36:13

回答

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