Pregunta

Estoy tratando de envolver palabras y secuencia de palabras de una lista dada con preg_replace. Casi funciona, pero hay algunos casos de uso no y no puedo calcularlo cómo.

Por ejemplo, yo hago esto:

    // 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 esta lista de palabras clave:

  • lorem
  • ipsum
  • sit amet
  • nula
  • sed
  • sed enim

Me gustaría dar lugar a:

  

-Lorem - -ipsum - dolor -Siéntate amet - ,   consectetur adipiscing elit. Phasellus   rhoncus venenatis Orci SED porta. sed   sin dolor eros. Suspendisse una Massa    -Siéntate amet - nulla egestas facilisis. Cras   fringilla, ac leo Ullamcorper semper,   urna eros pretium lectus, rhoncus nec   ligula RISUS eu velita. nulla eu   dapibus magna. Sed vehicula tristique   Lacinia. Mecenas tincidunt metus en   urna consequat ncp congue libero   iaculis. Nulla facilisi. Phasellus -sed -   sem ut RISUS Mattis accumsan eu -sed   ENIM - . Pellentesque habitant morbi   tristique senectus et Netus et   malesuada famas ac turpis egestas.   Suspendisse id est velita, cursus eu   quam. Vivamus Lacinia euismod Pretium.

¿Alguna idea?

¿Fue útil?

Solución 2

I finalmente resuelto mis problemas mediante el uso de los meta-caracteres \b que corresponden a un límite de palabra.

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

Otros consejos

El más fácil es utilizar preg_replace_callback(), y coinciden con las palabras que ya ha sido envuelto, y cada palabra clave. Cuando el partido es una palabra que se ha envuelto, apenas la vuelve sin modificar. No hay necesidad de problemáticas mirada-around.

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');
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top