regex — php preg_match_all / preg_replace обрезает замены для похожих совпадений

Я пытаюсь имитировать систему тегов хеша в Твиттере, заменяя все хэштеги на кликабельные ссылки. Я собрал фрагмент кода, который работает, но я обнаружил, что если два слова имеют одинаковые начала, более длинное слово заменяется (кликабельной ссылкой) на длину, на которой остановилось более короткое слово. то есть, если у меня есть предложение «#tool in #toolbox», #tool становится ссылкой, и только #tool в #toolbox становится ссылкой, а не весь #toolbox.

Ниже приведен фрагмент:

<?php//define text to use in preg_match and preg_replace
$text = '#tool in a #toolbox';

//get all words with hashtags
preg_match_all("/#\w+/",$text,$words_with_tags);

//if there are words with hash tags
if(!empty($words_with_tags[0])){

$words = $words_with_tags[0];

//define replacements for each tagged word,
//   $replacement     is an array of replacements for each word
//   $words            is an array of words to be replaced
for($i = 0; $i < sizeof($words) ; $i++ ){

$replacements[$i] = '<a href="'.trim($words[$i],'#').'">'.$words[$i].'</a>';

// format word as /word/ to be used in preg_replace
$words[$i] = '/'.$words[$i].'/';
}

//return tagged text with old words replaced by clickable links
$tagged_text = preg_replace($words,$replacements,$text);

}else{
//there are no words with tags, assign original text value to $tagged_text
$tagged_text = $text;
}echo $tagged_text;?>

1

Решение

Как насчет отлов и делает простой preg_replace ()

$tagged_text = preg_replace('~#(\w+)~', '<a href="\1">\0</a>', $text);

Тест на eval.in выходы на:

<a href="tool">#tool</a> in a <a href="toolbox">#toolbox</a>

Тест в regex101

1

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

Ты можешь использовать preg_replace_callback

<?php

$string = "#tool in a #toolbox";

$str = preg_replace_callback(
'/\#[a-z0-9]+/',
function ($matches) {
return "<a href=\"". ltrim($matches[0], "#") ."\">". $matches[0] ."</a>";
}, $string);
echo $str;
//Output: <a href="tool">#tool</a> in a <a href="toolbox">#toolbox</a>

https://eval.in/198848

0

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