Как можно избежать добавления href к перекрывающемуся ключевому слову в строке?

Используя следующий код:

$text = "أطلقت غوغل النسخة المخصصة للأجهزة الذكية العاملة بنظام أندرويد من الإصدار “25″ لمتصفحها الشهير كروم.ولم تحدث غوغل تطبيق كروم للأجهزة العاملة بأندرويد منذ شهر تشرين الثاني العام الماضي، وهو المتصفح الذي يستخدمه نسبة 2.02% من أصحاب الأجهزة الذكية حسب دراسة سابقة. ";
$tags = "غوغل, غوغل النسخة, كروم";
$tags = explode(",", $tags);
foreach($tags as $k=>$v) {
$text = preg_replace("/\b{$v}\b/u","<a href=\"index.php?s=news&tag=$0\">$0</a>",$text, 1);
}
echo $text;

Даст следующий результат:

I <a href="index.php?s=news&tag=<a href="index.php?s=news&tag=love">love</a> <a href="index.php?s=news&tag=PHP">PHP</a>">love PHP</a>, but I am <a href="index.php?s=news&tag=facing">facing</a> a problem

Обратите внимание, что мой текст на арабском языке.

1

Решение

Способ сделать все за один проход. Идея состоит в том, чтобы создать шаблон с чередованием тегов. Чтобы этот способ работал, вы должны предварительно отсортировать теги, потому что механизм регулярных выражений остановится на первой успешной альтернативе (в противном случае «любовь» всегда будет совпадать, даже если за ней следует «php», а «любовь php» никогда не будет сопоставлена). ).

Чтобы ограничить замену первым вхождением каждого слова, вы можете удалить тег из массива, как только он найден, и проверить, всегда ли он присутствует в массиве внутри функции обратного вызова замены:

$text = 'I love PHP, I love  love but I am facing a problem';
$tagsCSV = 'love, love php, facing';

$tags = explode(', ', $tagsCSV);

rsort($tags);

$tags = array_map('preg_quote', $tags);

$pattern = '/\b(?:' . implode('|', $tags) . ')\b/iu';

$text = preg_replace_callback($pattern, function ($m) use (&$tags) {
$mLC = mb_strtolower($m[0], 'UTF-8');
if (false === $key = array_search($mLC, $tags))
return $m[0];

unset($tags[$key]);
return '<a href="index.php?s=news&tag=' . rawurlencode($mLC)
. '">' . $m[0] . '</a>';
}, $text);

Примечание: когда вы создаете URL, вы должны кодировать специальные символы, поэтому я использую preg_replace_callback вместо preg_replace быть в состоянии использовать rawurlencode,

Если вам приходится иметь дело со строкой в ​​кодировке utf8, вам нужно добавить в шаблон модификатор u, и вам нужно заменить strtolower с mb_strtolower)

preg_split путь

$tags = explode(', ', $tagsCSV);

rsort($tags);

$tags = array_map('preg_quote', $tags);

$pattern = '/\b(' . implode('|', $tags) . ')\b/iu';

$items = preg_split($pattern, $text, -1, PREG_SPLIT_DELIM_CAPTURE);

$itemsLength = count($items);
$i = 1;
while ($i<$itemsLength && count($tags)) {
if (false !== $key = array_search(mb_strtolower($items[$i], 'UTF-8'), $tags)) {
$items[$i] = '<a href="index.php?s=news&tag=' . rawurlencode($tags[$key])
. '">' . $items[$i] . '</a>';
unset($tags[$key]);
}
$i+=2;
}

$result = implode('', $items);
0

Другие решения

Вы должны проверить свой tags для вложенных слов, и добавьте отрицательные взгляды:

$tags = "love(?! php), love php, facing";
0

Вместо звонка preg_replace несколько раз, назовите его один раз с регулярным выражением, которое соответствует любому из тегов:

$tags = explode(",", tags);
$tags_re = '/\b(' . implode('|', $tags) . ')\b/u';
$text = preg_replace($tags_re, '<a href="index.php?s=news&tag=$0">$0</a>', $text, 1);

Это превращает список тегов в регулярное выражение /\b(love|love php|facing)\b/u, x|y в регулярном выражении означает соответствие либо x или же y,

0
По вопросам рекламы [email protected]