Помогите с preg_replace

12
V3
На сайте с 08.09.2015
Offline
54
1087

Привет. На сайте давно используется автоматическая перелинковка страниц с помощью функции, ищущей нужные слова благодаря preg_replace. На днях столкнулся с проблемой, которая заключается в том, что функция заменяет на ссылки не только нужные слова, но и куски более длинных.

$text = preg_replace('~' . $value['faq_menu'] . '([\s\.\,])~is', '<a href="/faq/' . $value['faq_url'] . '/">' . $value['faq_menu'] . '</a>\1', $text);

Самым логичным вариантом показалось добавление модификатора \b, получился вот такой код:

$text = preg_replace('~\b' . $value['faq_menu'] . '\b([\s\.\,])~is', '<a href="/faq/' . $value['faq_url'] . '/">' . $value['faq_menu'] . '</a>\1', $text);

Который отказался работать. Погуглив, я узнал, что с кириллицей этот модификатор в принципе не работает, хотя у некоторых людей почему-то таких проблем нет. Ничего дельного я не нашёл, поэтому решил спросить совет здесь. Используется UTF-8 если это важно.

Как-то странно код вставился, позаменял символы. Вот было и стало:

$text = preg_replace('~' . $value['faq_menu'] . '([\s\.\,])~is', '<a href="/faq/' . $value['faq_url'] . '/">' . $value['faq_menu'] . '</a>\1', $text);

$text = preg_replace('~\b' . $value['faq_menu'] . '\b([\s\.\,])~is', '<a href="/faq/' . $value['faq_url'] . '/">' . $value['faq_menu'] . '</a>\1', $text);

bay_ebook
На сайте с 28.05.2010
Offline
111
#1
v1p3rrrrr:
Используется UTF-8 если это важно.

Для многобайтовых нужен U

~is меняем на ~Uis

Нужен прогер на php+mysql+понимание чужего кода? (/ru/forum/540660) Вам сюда PHP-шаман (http://php-shaman.pw/)
V3
На сайте с 08.09.2015
Offline
54
#2

А если и

$text = preg_replace('~\b' . $value['faq_menu'] . '\b([\s\.\,])~Uis', '<a href="/faq/' . $asg['faq_url'] . '/">' . $value['faq_menu'] . '</a>\1', $text, 1);

не работает, в какую сторону копать?

bay_ebook
На сайте с 28.05.2010
Offline
111
#3
v1p3rrrrr:
А если и
$text = preg_replace('~\b' . $value['faq_menu'] . '\b([\s\.\,])~Uis', '<a href="/faq/' . $asg['faq_url'] . '/">' . $value['faq_menu'] . '</a>\1', $text, 1);

не работает, в какую сторону копать?

([\s\.\,]) - не указана длина символов

([\s\.\,]{1,}) - как-то так

и \b я наверно убрал бы, тут нужно прогуляться с вариантами с этим \b

И для вставки кода используйте цитату, а не "код" в редакторе форма.

V3
На сайте с 08.09.2015
Offline
54
#4

Погуглил ещё, попробовал сделать

$text = preg_replace('~(?:\A|\s)' . $value['faq_menu'] . '(?:\s|\Z)~', '<a href="/faq/' . $value['faq_url'] . '/">' . $value['faq_menu'] . '</a>\1', $text, 1);

Стало находить нормально, но кушает пробелы при замене. В принципе, можно было бы просто добавить пробелы в замене, но тогда всё сломается, если будет конец предложения.

$text = preg_replace('/[^а-я]*' . $value['faq_menu'] . '[^а-я]*/isU', '<a href="/faq/' . $value['faq_url'] . '/">' . $value['faq_menu'] . '</a>\1', $text, 1);

Такой вариант тоже работает, но также любит пробелы съедать.

Но это уже фигня какая-то, у некоторых модификатор \b спокойно работает.

J
На сайте с 20.02.2014
Offline
120
jkm
#5
bay_ebook:
Для многобайтовых нужен U

~is меняем на ~Uis

Только вот модификатор U (PCRE_UNGREEDY) вовсе не для этого. Он просто инвертирует жадность квантификаторов.

Тут нужен u (PCRE_UTF8). http://php.net/manual/ru/reference.pcre.pattern.modifiers.php

~is меняем на ~uis

bay_ebook
На сайте с 28.05.2010
Offline
111
#6
v1p3rrrrr:

Стало находить нормально, но кушает пробелы при замене.

какие пробелы?

---------- Добавлено 14.01.2016 в 23:31 ----------

А вообще, готовое решение по вашему вопросу такое:

preg_replace("/b" . $value['faq_menu'] . "b/ui", '<a href="/faq/' . $value['faq_url'] . '/">' . $value['faq_menu'] . '</a>\1', $text);
V3
На сайте с 08.09.2015
Offline
54
#7
jkm:
Только вот модификатор U (PCRE_UNGREEDY) вовсе не для этого. Он просто инвертирует жадность квантификаторов.
Тут нужен u (PCRE_UTF8). http://php.net/manual/ru/reference.pcre.pattern.modifiers.php
~is меняем на ~uis

В том-то и дело, что u не сработал, его я пытался использовать ещё до создания темы здесь.

bay_ebook:
какие пробелы?

лаллала нужное_слово лалала меняет на лаллаланужное_словолалала

bay_ebook:
А вообще, готовое решение по вашему вопросу такое:

Не работает любой preg_replace, если использовать /b. Ни на локалке, ни на сервере.

Возможно, что-то не так с содержимым переменной, хотя вроде всё окей, кодировка точно UTF-8.

bay_ebook
На сайте с 28.05.2010
Offline
111
#8
v1p3rrrrr:

Возможно, что-то не так с содержимым переменной, хотя вроде всё окей, кодировка точно UTF-8.

Вот .проверил, символы в переменной, перед загрузкой нужно экранировать, b не нужен вроде

$text = 'asdas dfsg5y dhjrij// 54645 dfhksoh 00';
$replace = 'dhjrij//';
$replace = str_ireplace(['/', '#', '$', '^', '.'], ['\/', '\#', '\$', '\^', '\.'], $replace);
$url = 'anyurl.html';
$text = preg_replace("/".$replace."/ui", '<a href="/faq/'.$url.'">'.$replace.'</a>', $text);
echo $text;
V3
На сайте с 08.09.2015
Offline
54
#9

Вырезает из слов по-прежнему.

<?php
header("Content-Type: text/html; charset=utf-8");
$text = 'лалаланужное_словолалала нужное_слово лалала';
$replace = 'нужное_слово';
$replace = str_ireplace('[\'/\', \'#\', \'$\', \'^\', \'.\']', '[\'\/\', \'\#\', \'\$\', \'\^\', \'\.\']', $replace);
$url = 'anyurl.html';
$text = preg_replace('/'.$replace.'/ui', '<a href="'.$url.'">'.$replace.'</a>', $text);
echo $text;

На выходе оба становятся ссылками. Думаю, без \b тут не разобраться. Пока что чуть изменил тексты, в которых происходила ненужная замена, но это такой себе костыль.

J
На сайте с 20.02.2014
Offline
120
jkm
#10

Ну раз \b не работает с кириллицей в UTF-8, то можно попробовать через cвойства unicode-символов.


/(?<!\p{L})слово(?!\p{L})/u

Шаблон проверяет, что вокруг слова нет других букв.


$text = 'лалаланужное_словолалала нужное_слово лалала';
$replace = 'нужное_слово';
$url = 'anyurl.html';
$text = preg_replace('/(?<!\p{L})'.preg_quote($replace, '/').'(?!\p{L})/ui', '<a href="'.$url.'">'.$replace.'</a>', $text);
echo $text;
12

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий