2010-10-13 2 views
0

J'essaye d'emballer les mots et la séquence de mots d'une liste donnée avec preg_replace. Cela fonctionne presque, mais il y a des cas d'utilisation qui ne le sont pas et je n'arrive pas à comprendre comment.Comment faire pour envelopper des mots ou des séquences de mots qui n'ont pas déjà été enveloppés?

Par exemple, je fais ceci:

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

A partir de cette liste de mots clés:

  • lorem
  • ipsum
  • sit amet
  • null
  • sed
  • enim sed

Je voudrais entraîner:

-Lorem--ipsum- dolor -sit amet-, consectetur adipiscing elit. Phasellus rhoncus venenatis orci sed porta. Sed non dolor eros. Suspendisse a massa -sit amet- nulla egestas facilisis. Cras fringilla, leo ac ullamcorper sempre, urne eros pretium lectus, nec rhoncus ligula risus eu velit. Nulla eu dapibus magna. Sed vehicula tristique lacinia. Mécène tincidunt metus au urna consequat nec congue libero iaculis. Nulla facilisi. Phasellus -sed- sutus matus accumsan eu -sed enim-. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Suspendisse id est velit, eu cursus quam. Vivamus lacinia euismod pretium.

Des idées?

+0

Quel est le problème spécifique que vous rencontrez? – Roadie57

Répondre

0

J'ai finalement résolu mes problèmes en utilisant les \b métacaractères qui correspondent à une limite de mot.

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

Le plus simple est d'utiliser preg_replace_callback(), et de faire correspondre les mots qui ont déjà été enveloppés, et chaque mot-clé. Lorsque le mot correspond à un mot, il suffit de le renvoyer non modifié. Pas besoin de look-around problématique.

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