Wie Wörter oder Worte Sequenzen wickeln, die noch nicht eingewickelt worden?
-
29-09-2019 - |
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?
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');
}