Frage

Ich versuche, Worte und Worte Sequenz aus einer vorgegebenen Liste mit preg_replace zu wickeln. Es funktioniert fast, aber es gibt einige Anwendungsfälle es nicht, und ich kann es nicht verstehen, wie.

Zum Beispiel ich dies tun:

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

Von dieser Keyword-Liste:

  • Lorem
  • ipsum
  • sit amet
  • null
  • sed
  • sed enim

Ich möchte zu folgenden Ergebnissen führen:

  

-Lorem - -ipsum - dolor -sit amet - ,   consectetur adipiscing elit. Phasellus   rhoncus venenatis orci sed porta. sed   Nicht dolor eros. Suspendisse ein massa    -sit amet - nulla egestas facilisis. Cras   fringilla, leo ac ullamcorper semper,   urna eros pretium lectus ang rhoncus   ligula RISUS eu velit. nulla eu   dapibus magna. Sed vehicula Tristique   lacinia. Maecenas tincidunt metus bei   urna consequat ang 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.   Suspendisse id est velit, eu cursus   quam. Vivamus lacinia euismod pretium.

Irgendwelche Ideen?

War es hilfreich?

Lösung 2

ich meine Probleme endlich gelöst, indem die \b Metazeichen mit denen entsprechen einer Wortgrenze.

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

Andere Tipps

Am einfachsten ist preg_replace_callback() zu verwenden und Wörter übereinstimmen, die bereits eingewickelt wurde, und jedes Schlüsselwort. Wenn das Spiel ein Wort, das eingewickelt wurde, kehrt nur unmodifizierte es. Keine Notwendigkeit für problematischen Look-arounds.

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');
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top