Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: Поставить урл у слова и словосочитания (где есть такое же слово)
Форумы портала PHP.SU » PHP » Регулярные выражения » Поставить урл у слова и словосочитания (где есть такое же слово)

Страниц (1): [1]
 

1. Dilex - 08 Июня, 2010 - 18:19:20 - перейти к сообщению
У меня есть текст в ней много слов, которые необходимо заменить на соответствующие урлы.

Я написал функцию:
PHP:
скопировать код в буфер обмена
  1.  
  2. function name_to_url ($www)
  3. {
  4. $url_derevo='
  5. купить амулет делового человека=talisman_delovogo_cheloveka.html
  6. талисман путешественника=talisman_puteshestvennika.html
  7. талисман=talisman.html
  8. дуб исполин=derevo_schastiya_iz_kamnei_dub_ispolin_kupit.html';
  9.  
  10. $all_name=$url_derevo;
  11.  
  12.     $name = explode("\n", $all_name);
  13.         foreach ($name as $key => $value)
  14.         {
  15.                 $n = explode("=", $value);
  16.                 //echo $key.')'.$n [0].'='.$n [1];
  17.                 $n[1]=str_replace("\n","",$n[1]);
  18.                 $www = eregi_replace($n[0], "<a href='".$n[1]."'>\\0</a>", $www);
  19.                 // можно вписать
  20.         }
  21. return $www;
  22. }
  23.  
  24.  


Например есть такой текст:
"На этом сайте вы можете приобрести талисман по знакам зодиака.
А так же талисман путешественника и другие."

Если я пропущу этот текст через функцию, то получится вот:
CODE (html):
скопировать код в буфер обмена
  1. "На этом сайте вы можете приобрести <a href:talisman.html>талисман</a> по знакам зодиака. А так же <a href:talisman.html>талисман</a> путешественника и другие."


Как сделать чтобы получалось вот так:
CODE (html):
скопировать код в буфер обмена
  1. "На этом сайте вы можете приобрести <a href:talisman.html>талисман</a> по знакам зодиака. А так же <a href:talisman_puteshestvennika.html>талисман путешественника</a> и другие."


Заранее спасибо за ответ.
2. JustUserR - 09 Июня, 2010 - 11:21:11 - перейти к сообщению
Dilex пишет:
Как сделать чтобы получалось вот так
В вашем случае используемое POSIX-регулярное выражение выполняет исключательно функцию замены подстрок - и в таком случае решением будет упорядочивание искомых подстрок в порядке убывания длины чтобы сначала заменялась самая длинная и тд - и при этом для того чтобы при проходе по более короткой подстроке которую включала в себя более длинная нужно проверить к примеру наличие a-href-тега слева и не проводить повторную замену
Более эффективным способом было бы использование PCRE-регулярного выраржния по вышеуказанному алгоритму - то есть проходите по всем искомым строкам с учетом длины и перед очередной заменой проверяете не был ли уже использован данный текст
3. Dilex - 09 Июня, 2010 - 11:41:49 - перейти к сообщению
Спасибо. Отличная идея.
4. JustUserR - 09 Июня, 2010 - 11:46:00 - перейти к сообщению
Dilex пишет:
Спасибо. Отличная идея.
Пожалуйста! Заметьте также что такой вариант является одним из самых быстродейственных - поскольку хотя перед каждой вставкой он использует дополнительную проверку на факт прохождения подстрокой определенной обработки - но если хранить строковые позиции обработанных значений то их перерасчет при каждой итерации занимал бы большее время особенно при росте объема обрабатываемых данных
5. Dilex - 18 Июня, 2010 - 23:59:38 - перейти к сообщению
C первого взгляда, было понятно как это сделать, а как дошло до дела, сразу возникли вопросы Улыбка
Почему-то функция eregi_replace() , сначала заменяет короткие строки, а потом длинные , причем от перестановки выше или ниже, замена не зависит. Если я введу ниже описанные строки, то он заменит, только "аму", а "амулет", вообще заменять не будет.
PHP:
скопировать код в буфер обмена
  1. $www = ereg_replace("амулет", "<a href='derevo_schastiya'>\\0</a>", $www);
  2. $www = ereg_replace("аму", "<a href='derevo_schastiya'>\\0</a>", $www);


Использовал так же preg_replace(), результат такой же.

Буду разбираться дальше.
Если подскажите, советом. Будет хорошо.
6. Champion - 19 Июня, 2010 - 09:49:51 - перейти к сообщению
PHP:
скопировать код в буфер обмена
  1. <?PHP
  2. function name_to_url ($www)
  3. {
  4. $url_derevo='купить амулет делового человека=talisman_delovogo_cheloveka.html
  5. талисман путешественника=talisman_puteshestvennika.html
  6. талисман=talisman.html
  7. дуб исполин=derevo_schastiya_iz_kamnei_dub_ispolin_kupit.html';
  8.  
  9. $all_name=$url_derevo;
  10.  
  11.     $name = explode("\n", $all_name);
  12.         $www = preg_replace('/\s+/', ' ', $www);
  13.     foreach ($name as $key => $value)
  14.     {
  15.         $n = explode("=", trim($value));
  16.        $www = preg_replace("/((?:<\/a>|^)[^<]*)({$n[0]})/i", "\\1<a href='".$n[1]."'>\\2</a>", $www);
  17.         // можно вписать
  18.     }
  19. return $www;
  20. }
  21.  
  22. echo name_to_url ("На этом сайте вы можете приобрести талисман по знакам зодиака.
  23. А так же талисман путешественника и другие.");
  24. ?>

(Добавление)
Просто штука в том, что по первому ключу всё действительно заменялось, а после этого заменялось по второму. И получалась штуковина типа
текст <a href=talisman_putesestv.html><a href=talismanv.html>талисман</a>путешественника</a>.
И браузер отобразил такую вещь так, как посчитал нужным. А надо просто при замене проверять, не заменяем ли мы внутри уже произведенной замены.
7. Dilex - 19 Июня, 2010 - 10:55:04 - перейти к сообщению
Спасибо за ответ Champion.

Ввел вышеописанный код.
И расширил текст:
PHP:
скопировать код в буфер обмена
  1. echo name_to_url ("На этом сайте вы можете приобрести талисман по знакам зодиака.
  2. А так же талисман путешественника и другие. Талисман путешественника помогает в пути");


Результат был таков:
CODE (html):
скопировать код в буфер обмена
  1. На этом сайте вы можете приобрести талисман по знакам зодиака. А так же <a href='talisman.html'>талисман</a> путешественника и другие. <a href='talisman_puteshestvennika.html'>Талисман путешественника</a> помогает в пути


Т.е. в укороченном варианте текста, все получается, а вот в длинном ... Недовольство, огорчение
8. JustUserR - 19 Июня, 2010 - 11:41:40 - перейти к сообщению
Dilex пишет:
Т.е. в укороченном варианте текста, все получается, а вот в длинном
Дело может быть в наличии регулярных выражений жадных квантификаторов и в неправильном порядке заменяемых шаблонов По этой причине схема должны быть несколько универсализирована чтобы оригинальный порядок следования не имел значения и каждая замена могла применяется сколько угодно раз - конкретно для этого функция расставляет шаблоны в порядке уменьшения их длины и для каждого из шаблонов запускает регулярное выражение с полным поиском Также было бы полезно учитывать различные словоформы - для этих целей применяется алгоритм типа Стеммера Портера
9. Champion - 19 Июня, 2010 - 12:41:43 - перейти к сообщению
По поводу словоформ, можно просто самому в ключах задать неизменяемые части слова, а матчить примерно так/$key\w+/.
А по поводу замены - да, она так срабатывает. Если по-простому, то в строке 455555655556 шаблон /4\d+?(6)/ сматчится только одна шестерка...

Наиболее простым способом мне кажется использовать preg_replace_callback, которая <a href...> C ВОТ ЭТОИМ</a> сделает htmlspecialchars, чтоб оно больше не матчилось.
(Добавление)
Только регулярку эту убрать /((?:<\/a>|^)[^<]*)({$n[0]})/i и сделать простоую вот эту /($n[0])/i. Ну и ключи надо располагать не забывать в порядке убывания длин, как ты и сделал, и как напомнил JusrUserR
10. JustUserR - 20 Июня, 2010 - 13:23:15 - перейти к сообщению
Champion пишет:
По поводу словоформ, можно просто самому в ключах задать неизменяемые части слова
Да в принципе можно сделать и так и в большинстве слов это будет работать - проблема только со словами в который при изменении грамматической формы меняется корень или он короткий и неочевидный для проверки Но в общем для системы цель которой не алаиз текста а генерация рекламных ссылок - это более чем подходящий вариант
11. Dilex - 22 Июня, 2010 - 14:15:39 - перейти к сообщению
Уф-фф. Наконец-то сделал.
Я не сразу сообразил, что надо html кода смотреть, а смотрел на результат
вывода в броузер. А броузер выводил только ссылки с самым минимальным
количеством букв. Поэтому у меня было удивление, почему про эту проблему
никто ничего не пишет Улыбка. А когда открыл html код сразу увидел о чем писал
JustUserR.

Вот код в котором расставляются ссылки, с условием, что
ссылка не ставится второй раз:

PHP:
скопировать код в буфер обмена
  1.         foreach ($name_sort as $key => $value)
  2.         {
  3.                 $n = explode("=", $value);
  4.                 $n[1]=str_replace("\r","",$n[1]);
  5.                 $www = ereg_replace(" ".$n[0], " <a href='".$n[1]."'>".$n[0]."</a>", $www);
  6.         }
  7.  


Может не идеально, но для моих нужд сгодится.

Сортировку по длине ссылок тоже сделал, как и рекомендовали.
Всем спасибо за ответы !
12. JustUserR - 22 Июня, 2010 - 14:27:22 - перейти к сообщению
Dilex пишет:
Поэтому у меня было удивление, почему про эту проблему
никто ничего не пишет . А когда открыл html код сразу увидел о чем писал
JustUserR.
Это весьма стандартныый вопрос при работе со строковыми данными - именно поэтому в машине регулярных выражений была добавлена возможность поиска назад и вперед

 

Powered by ExBB FM 1.0 RC1