Как обернуть слова или последовательности слов, которые еще не были обернуты? - PullRequest
0 голосов
/ 13 октября 2010

Я пытаюсь обернуть слова и последовательность слов из заданного списка с помощью 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);
    }

Из этого списка ключевых слов:

  • Lorem
  • Ipsum
  • сит амет
  • пустой
  • 1017 * СЭД *
  • sed enim

Я бы хотел получить:

-Lorem- -ipsum- dolor -sit amet- , Concectetur Adipiscing Elit. Phasellus rhoncus venenatis orci sed porta. Sed не долор эрос. Suspendisse Масса -сайт амет- nulla egestas facilisis. Крас fringilla, leo ac ullamcorper semper, урна эрос претиум лектус ligula risus eu Velit. Нулла ес дапибус магна. Sed Vehicleula tristique лациния. Меценат опоясывающий лишай метус в урна конквестат nec congue libero iaculis. Nulla facilisi. Phasellus -sed- sem ut risus mattis accumsan eu -sed enim- . Местный житель морби трилистик сенектус и нетус эт malesuada fames ac turpis egestas. Suspendisse ID Est Velit, ЕС Курсус Ква. Vivamus Lacinia Euismod Pretium.

Есть идеи?

Ответы [ 2 ]

1 голос
/ 13 октября 2010

Проще всего использовать 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');
}
0 голосов
/ 15 октября 2010

Я наконец решил свои проблемы, используя метасимволы \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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...