Как обернуть слова или последовательности слов, которые еще не были обернуты?
-
29-09-2019 - |
Вопрос
Я пытаюсь завершить последовательность слов и слов из данного списка с 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);
}
Из этого списка ключевых слов:
- Лорем
- ipsum
- сидеть амит
- нулевой
- Сед
- Sed Enim
Я хотел бы привести к:
-Лум- -Пипсум- Долор -Сит амет-, Consectetur Adipiscing Elit. Phasellus rhoncus venenatis orci sed porta. SED NON DOLOR EROS. Приостановка Масса -Сит амет- Nulla Egestas farsilisis. Cras Fringilla, Leo Ac Ullamcorper Semper, Urna Eros Pretium Lectus, Nec Rhoncus Ligula Risus Eu Velit. Nulla Eu Dapibus Magna. SED ETHICULA TRISTIQUE LACINIA. Maecenas tincidunt Metus в Urna exclive nec Congue Libero Iaculis. Nulla farsilisi. Phasellus -сед-Sem ut Risus mattis accumsan eu -Пет Enim-. Анкет Pallentesque Hainatant Morbi Tristique Senectus et Netus et Malesuada Fames ac turpis egestas. SUSPERNDISSE ID EST VELIT, EU Cursus Quam. Vivamus lacinia euuismod pretium.
Любые идеи?
Решение 2
Я наконец решил свои проблемы, используя \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;
}
Другие советы
Проще всего использовать 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');
}