Preg Replace - заменить второе вхождение совпадения

Я относительно новичок в php и надеюсь, что кто-то может помочь мне с заменой регулярного выражения или, может быть, заменой соответствия, я не совсем уверен.

Я хочу автоматически выделить жирным шрифтом (второе появление совпадения), а затем сделать 4-е появление совпадения курсивом, а затем 7-е появление совпадения подчеркнутым.

Это в основном для целей SEO в содержании.

Я сделал несколько замен на: и думал, что это должно помочь?

preg_replace( pattern, replacement, subject [, limit ])

Я уже знаю слово, которое хочу использовать в

'pattern' is also a word that is already defined like [word].
`replacement` 'This is a variable I am getting from a mysql db.
'subject' - The subject is text from a db.

Допустим, у меня есть этот контент: это более или менее объясняет, что я хочу делать.

Это пример текста, который я хочу заменить. В этом тексте я хочу выделить второе появление слова example ‹ полужирным шрифтом. Затем я хочу пропустить следующий раз, когда пример встречается в тексте, и сделать четвертый раз, когда слово пример появляется курсивом. Затем я хочу пропустить 5-й раз, когда в тексте появляется слово example, а также 6-й раз и, наконец, хочу сделать 7-й раз пример появится в тексте, подчеркните его. В этом примере я использовал гиперссылку в качестве примера подчеркивания, поскольку я не вижу функции подчеркивания в текстовом редакторе. Слово пример может встречаться в тексте несколько раз, но мое единственное требование — один раз подчеркнуть, один раз выделить жирным шрифтом и один раз выделить курсивом. Возможно, позже я решу сделать несколько кавычек со словом «пример», но это пока не является приоритетом.

Также важно, чтобы код не выдавал ошибку, если слово встречается не менее 7 раз.

Как бы я это сделал, любые идеи будут оценены.


person Gerald Ferreira    schedule 16.04.2011    source источник


Ответы (3)


Вы можете использовать preg_split, чтобы разделить текст на совпадения, применить изменения, а затем собрать все обратно:

$parts = preg_split('/(example)/', $str, 7, PREG_SPLIT_DELIM_CAPTURE);
if (isset($parts[3])) $parts[3] = '<b>'.$parts[3].'</b>';
if (isset($parts[7])) $parts[7] = '<i>'.$parts[7].'</i>';
if (isset($parts[13])) $parts[13] = '<u>'.$parts[13].'</u>';
$str = implode('', $parts);

Формула индекса для i-го совпадения: index = i · 2 - 1.

person Gumbo    schedule 16.04.2011
comment
Спасибо Гамбо! Я могу почти сразу же начать отправлять все свои вопросы непосредственно вам :-) в большинстве случаев вы тот, у кого есть ответы, которые работают! Бесконечно благодарен. - person Gerald Ferreira; 16.04.2011
comment
Привет, Гамбо, теперь я полностью запутался. Я использовал код на этой странице 24hour-casino-games.com/ Casino-reviews/online/ h1 не является частью строки. Итак, если я посчитаю слова May Flower Casino. Цветочное казино 2 мая выделено, что правильно. Затем, когда он используется в четвертый раз, он выделен курсивом, что правильно. а затем, если я сделаю значение после $str, 7 (14), оно покажет еще один полужирный шрифт в позиции 7, что правильно. не могли бы вы объяснить мне, почему $parts[7] отображается на позиции 4, а $parts[13] на позиции 7... Спасибо - person Gerald Ferreira; 16.04.2011
comment
@Gerald Ferreira: когда preg_split захватывает разделитель (соответствие шаблону), результатом всегда является нечетное количество частей, где каждая четная часть с нечетным индексом (начиная с нуля) является разделителем. Таким образом, первый разделитель равен 1, второй — 3, третий — 5 и т. д. И это можно выразить с помощью i · 2 - 1. - person Gumbo; 16.04.2011
comment
хорошо - теперь это имеет смысл, спасибо, Гамбо. Теперь я увеличил число на 1 — тогда он выделяет весь текст между «Майским цветком» и «Майским цветком», и если я снова делаю нечетным, он выбирает слово! - Большое спасибо за помощь - это отличное решение! - Я вижу, что подчеркивание обесценилось, поэтому я скорее пойду со ссылкой... - person Gerald Ferreira; 16.04.2011

Само по себе регулярное выражение не может считать, а функции preg_ мало чем помогают. Вам нужен обходной путь. Если бы вы действительно искали только слово, вы могли бы использовать строковые функции. В противном случае попробуйте:

// just counting
if (7 >= preg_match_all($pattern, $subject, $matches)) {

   $cb_num = 0;
   $subject = preg_replace_callback($pattern, "cb_ibu", $subject);
}

function cb_ibu($match) {
    global $cb_num;

    $match = $match[0];

    switch (++$cb_num) {
        case 2: return "<b>$match</b>";
        case 4: return "<i>$match</i>";
        case 7: return "<u>$match</u>";
        default: return $match;
    }
}

Хитрость заключается в том, чтобы иметь обратный вызов, который ведет учет. И туда довольно легко добавить любые правила.

person mario    schedule 16.04.2011
comment
Спасибо, Марио, сейчас проверю... просто чтобы убедиться - person Gerald Ferreira; 16.04.2011
comment
$pattern = '/[слово]/' $subject = ?, $matches = ? Я не знаю, что указать в теме и соответствиях... - person Gerald Ferreira; 16.04.2011
comment
$matches — это просто неиспользуемая одноразовая переменная. Но $subject — это ваш исходный текст. - person mario; 16.04.2011
comment
Я реализовал это так... $pattern = '/'.$g_page_identify.'/'; $subject = $g_page_content2; // просто считаем if (7 ›= preg_match_all($pattern, $subject, $matches)) { $cb_num = 0; $subject = preg_replace_callback($pattern, cb_ibu, $subject); } function cb_ibu($match) { global $cb_num; $матч = $матч[0]; switch (++$cb_num) { case 2: return ‹b›$match‹/b›; случай 4: вернуть ‹i›$match‹/i›; случай 7: вернуть ‹u›$match‹/u›; по умолчанию: вернуть $match; } } - person Gerald Ferreira; 16.04.2011
comment
Спасибо за отзыв, Марио, я ценю это, в конце концов я выбрал решение, предоставленное Gumbo. - person Gerald Ferreira; 16.04.2011
comment
@Gerald: тоже хороший выбор. Скорее всего, это более быстро. И вполне компактный и работоспособный для вашего случая. - person mario; 16.04.2011

Это интересный вопрос. Моя реализация будет:

function replace_exact($word, $tag, $string, $limit) {
    $tag1 = '<'.$tag.'>';
    $tag2 = '</'.$tag.'>';
    $string = str_replace($word, $tag1.$word.$tag2, $string, 1);
    if ($limit==1) return $string;
    return str_replace($tag1.$word.$tag2,$word,$string,$limit-1);
}

Используйте это так:

echo replace_exact('Example', 'b', $source_text, 2);
echo replace_exact('Example', 'i', $source_text, 4);

Я не знаю, насколько быстро это будет работать, но это будет быстрее, чем preg_replace.

person Alexander Ivanov    schedule 16.04.2011