Модераторы: Aliance, skyboy, MoLeX, ksnk

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Регулярка для поиска нескольких слов 
:(
    Опции темы
KgCoder
Дата 12.7.2009, 19:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 93
Регистрация: 6.3.2008
Где: KGstan

Репутация: нет
Всего: нет



Уже третий день курю ману по регулярке. :(
Помогите решить. Есть данные:
Код

$text = 'Река Каракол начинается далеко в горах. Основная часть реки протекает в ущелье Каракол,' .
  ' где замедляется и через несколько километров проходит через город Каракол.';
$tags = array(
  ...
  5 => 'река Каракол',
  7 => 'город Каракол',
  21 => 'ущелье Каракол',
  ...
);


Как заменить все встречающиеся элементы из перменной $tag, чтобы текст после обработки был таким:
Код

$output= '<a href="tag/TAG[ID]">Река Каракол</a> начинается далеко в горах.' .
  ' Основная часть реки протекает в <a href="tag/TAG[ID]">ущелье Каракол</a>' .
  ', где замедляется и через несколько километров проходит через <a href="tag/TAG[ID]">город Каракол</a>.';


Это сообщение отредактировал(а) KgCoder - 12.7.2009, 21:24
PM MAIL   Вверх
enof
Дата 12.7.2009, 19:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 837
Регистрация: 23.1.2009
Где: Санкт-Петербург

Репутация: 1
Всего: 35



Код

foreach($tags as $id=>$tag)
    $text = preg_replace('#('.preg_quote($tag, '#').')#iu', '<a href="tag/TAG['.$id.']">$1</a>', $text);

PM MAIL ICQ Skype   Вверх
ksnk
Дата 12.7.2009, 20:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 12
Всего: 386



Код

$text = 'Река Каракол начинается далеко в горах. Основная часть реки протекает в ущелье Каракол,' .
  ' где замедляется и через несколько километров проходит через город Каракол.';
$tags = array(
  5 => 'река Каракол',
  7 => 'город Каракол',
  21 => 'ущелье Каракол',
);
$GLOBALS['tags']=&$tags;
$reg=array();
// create regs
foreach($tags as $v){
  $reg[]=preg_replace('/\s+/si','\\s+',preg_quote($v));
}

//apply reg
echo preg_replace_callback('/('.implode(')|(',$reg).')/si',create_function('$matches','
    global $tags;
    $i=1;
    foreach($tags as $k=>$v){
        if(!empty($matches[$i])){
             return sprintf(\'<a href="tag/TAG%s">%s</a>\',$k,$v);
        }
        $i++;
    }
    return $matches[0];
'),$text);



--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
KgCoder
Дата 12.7.2009, 21:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 93
Регистрация: 6.3.2008
Где: KGstan

Репутация: нет
Всего: нет



При добавлении в массив $tags элемента:
Код

  ...
  1 => 'Каракол',
  ...

Теги повторно оборачиваются :(
PM MAIL   Вверх
ksnk
Дата 12.7.2009, 22:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 12
Всего: 386



KgCoder, в моем примере тоже?


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
enof
Дата 12.7.2009, 22:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 837
Регистрация: 23.1.2009
Где: Санкт-Петербург

Репутация: 1
Всего: 35



Цитата(ksnk @  12.7.2009,  21:36 Найти цитируемый пост)
preg_replace('/\s+/si','\\s+',preg_quote($v));

 smile 
PM MAIL ICQ Skype   Вверх
ksnk
Дата 12.7.2009, 23:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 12
Всего: 386



enof, O! 777 сообшений - нужно отметить! smile

Это про что смайлик? 
Я там, типо, защищаюсь от нескольких пробелов в tags и в эталонном тексте. что-то не так?


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
enof
Дата 12.7.2009, 23:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 837
Регистрация: 23.1.2009
Где: Санкт-Петербург

Репутация: 1
Всего: 35



Не могу понять, что такое "\\s+" в replacement и зачем юзать preg_quote для subject.
Цитата(ksnk @  13.7.2009,  00:08 Найти цитируемый пост)
O! 777 сообшений - нужно отметить! smile

 smile 
PM MAIL ICQ Skype   Вверх
ksnk
Дата 12.7.2009, 23:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 12
Всего: 386



enof, 
К примеру
Код

$tags=array(...
4=>'Где ты  Бетмен?', // 2 пробела случайно поставлено перед Бетмен
...
);
  preg_replace('/\s+/si','\\s+',preg_quote($v));
...
 выдаст чего-то наподобии 
Код

Где\s+ты\s+Бетмен\?
? что в общем-то примерно то, что и нужно было бы искать топикстартеру...
В принципе, два слеша не очень то и нужны, с одним тоже работает...



--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
enof
Дата 12.7.2009, 23:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 837
Регистрация: 23.1.2009
Где: Санкт-Петербург

Репутация: 1
Всего: 35



ааа, все ясно, затупил чет smile 
PM MAIL ICQ Skype   Вверх
KgCoder
Дата 13.7.2009, 05:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 93
Регистрация: 6.3.2008
Где: KGstan

Репутация: нет
Всего: нет



Эхм, спасибо. Сейчас пересядю на PC и попробую. И еще один вопрос. Если скажем элементов в массиве $tag будет > 500, система не нагрузиться? В принципе у меня есть кеширование, но всё-же не хотелось бы получить timeout из-за регулярок.
PM MAIL   Вверх
KgCoder
Дата 13.7.2009, 07:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 93
Регистрация: 6.3.2008
Где: KGstan

Репутация: нет
Всего: нет



В общем потестил. Выложу полный код (Drupal):
Код

    ...
    $result = db_query($query);
    while ($term = db_fetch_object($result)) {
      $glossary_term[$term->tid] = $term->name;
    }
    $GLOBALS['glossary_term'] = &$glossary_term;
    $reg = array();
    foreach($glossary_term as $v) {
      $reg[]=preg_replace('/\s+/si','\\s+',preg_quote($v));
    }
    $node->body = preg_replace_callback('/('.implode(')|(',$reg).')/si', create_function('$matches', '
      global $glossary_term;
      $i = 1;
      foreach($glossary_term as $k => $v) {
        if(!empty($matches[$i])){
          return sprintf(\'<span class="advanced-glossary-term info-tip" id="term-%d">%s</span>\', $k, $v);
        }
        $i++;
      }
      return $matches[0];
    '), $node->body);
    ...

Теги в массиве: Karakol river, Karakol peak, Karakol city, Karakol
Результат обработки: Karakol river, goes near Karakol peak and enters Karakol city. Once more Karakol

Сделал так:
Код

    ...
    $result = db_query($query);
    while ($term = db_fetch_object($result)) {
      $glossary_term[$term->tid] = $term->name;
    }
    foreach ($glossary_term as $tid => $term) {
      $pattern = '/\b(?<!\"|\/)' . $term . '\b/';
      $replacement = '<span class="advanced-glossary-term info-tip" id="term-' . $tid . '">' . $term . '</span>';
      if (variable_get('advanced_glossary_teaser', TRUE)) {
        $node->teaser = preg_replace($pattern, $replacement, $node->teaser,
          variable_get('advanced_glossary_link_first_only', true) ? 1 : -1);
      }
      $node->body = preg_replace($pattern, $replacement, $node->body,
        variable_get('advanced_glossary_link_first_only', true) ? 1 : -1);
    }
    ...

Теги в массиве: Karakol river, Karakol peak, Karakol city, Karakol
Результат: Karakol river, goes near Karakol peak and enters Karakol city. Once more Karakol

Желаемый результат: Karakol river, goes near Karakol peak and enters Karakol city. Once more Karakol
Если сказать короче, то каждый тег должен выделиться в тексте. Сейчас пытаюсь искать в модулях типа wiki, glossary, а также сторонних скриптах.

Добавлено через 4 минуты и 14 секунд
ksnk, enof, спасибо, что откликнулись. При завершении модуля, укажу вас в списке хороших людей на drupal.org. Мелочь а приятно. smile

Это сообщение отредактировал(а) KgCoder - 13.7.2009, 07:25
PM MAIL   Вверх
ksnk
Дата 13.7.2009, 08:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 12
Всего: 386



Цитата(KgCoder @  13.7.2009,  07:24 Найти цитируемый пост)
Желаемый результат...
Нужно отсортировать теги в массиве так, чтобы Karakol шел после Karakol river

Насчет эффективности - тут надо тестировать, но чем больше регулярка, тем она медленее "работает", так что 500 элементов - это, наверное, многовато...

Вообще-то можно заменить все найденные теги по методу  enof, но не на конечный "ссылочный" тег, а на какой-нибудь закорюк - @TAG[ID]@, к примеру. После полной замены всех тегов, поменять все закорюки на нужные ссылки, вторым "проходом" по массиву


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
KgCoder
Дата 13.7.2009, 10:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 93
Регистрация: 6.3.2008
Где: KGstan

Репутация: нет
Всего: нет



ksnk, При сортировке и использовании моего варианта будет работать? Я тут подумал над сортировкой. Кажется придётся при добавлении записей БД делать strlen и вставлять её как еще один параметр :( Или я усложняю?
PM MAIL   Вверх
KgCoder
Дата 13.7.2009, 11:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 93
Регистрация: 6.3.2008
Где: KGstan

Репутация: нет
Всего: нет



Сделал сортировку. Использую мой регулярку.
Результат: Karakol river, goes near Karakol peak and enters Karakol city. Once more Karakol
Тег Каракол будучи последним втискивается в уже отмеченный Karakol river. :(

Это сообщение отредактировал(а) KgCoder - 13.7.2009, 11:07
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Тексты | Следующая тема »


 




[ Время генерации скрипта: 0.0555 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.