2010-10-13 71 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'); 
}