2017-01-30 5 views
1

У меня есть массив слов и строка и вы хотите добавить хэштег к словам в строке, что они имеют соответствие внутри массива. Я использую этот цикл, чтобы найти и заменить слова:preg replace игнорирует небуквенные символы при обнаружении слов

foreach($testArray as $tag){ 
    $str = preg_replace("~\b".$tag."~i","#\$0",$str); 
} 

Проблема: позволяет сказать, что у меня есть слово «есть» и «изолировать» в моем массиве. Я получу ## изоляцию на выходе. это означает, что слово «изолировать» найдено один раз для «есть» и один раз «изолировать». И шаблон игнорирует тот факт, что «#isoldated» больше не начинается с «is», и начинается с «#».

я привожу пример, но это только exampl е, и я не хочу просто решить эту одну, а все остальные Possiblity:

$str = "this is isolated is an example of this and that"; 
$testArray = array('is','isolated','somethingElse'); 

выход будет:

this #is ##isolated #is an example of this and that 

ответ

1

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

$str = "this is isolated is an example of this and that"; 
$testArray = array('is','isolated','somethingElse'); 
echo preg_replace('~\b(?:' . implode('|', $testArray) . ')\b~i', '#$0', $str); 
// => this #is #isolated #is an example of this and that 

См. PHP demo.

Регулярное выражение будет выглядеть

~\b(?:is|isolated|somethingElse)\b~ 

Смотрите его online demo.

Если вы хотите, чтобы ваш подход работал, вы можете добавить отрицательный lookbehind после \b: "~\b(?<!#)".$tag."~i","#\$0". В lookbehind будут отсутствовать все совпадения, которым предшествует #. См. this PHP demo.

1

способ сделать это, чтобы разделить вашу строку слов и создать ассоциативный массив с исходным массивом слов (чтобы избежать использования in_array):

$str = "this is isolated is an example of this and that"; 
$testArray = array('is','isolated','somethingElse'); 

$hash = array_flip(array_map('strtolower', $testArray)); 

$parts = preg_split('~\b~', $str); 

for ($i=1; $i<count($parts); $i+=2) { 
    $low = strtolower($parts[$i]); 
    if (isset($hash[$low])) $parts[$i-1] .= '#'; 
} 

$result = implode('', $parts); 

echo $result; 

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