[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Нетипичные поиск/замена
FatCat
Есть система, которая метит в тексте сопоставленные слова из поискового запроса:
PHP
$txt str_replace($word,"<span class='darling'>".$word."<span>",$txt);


Проблема возникает при частичном совпадении слов при повторных поисковых запросах.

Например, текст "новое словообразование" при сопоставлении запросу по "слово" приобретает вид:
HTML
новое <span class='darling'>слово<span>образование


При повторном запросе "словообразование" сопоставление не происходит: "словообразование" не равно "слово<span>образование".

Для повторных сопоставлений попробовал использовать конструкцию, убирающую "лишние" теги:
PHP
$native_txt preg_replace"#<span class='darling'>(.+?)</span>#is""\\1"$txt );
if(
stristr($native_txt,$word))
{
// И что тут делать?!!!
}

Теперь сопоставления находятся. Но что сделать, чтобы новые выделения легли, не удаляя старых?
Как получить на выходе:
HTML
новое <span class='darling'><span class='darling'>слово<span>образование<span>
?



Спустя 1 час, 34 минуты, 49 секунд (2.02.2009 - 20:23) Sylex написал(а):
если я правильно тебя понял, то нужно заменять сначала самые длинные совпадения к меньшему, типа так:
PHP
<style type="text/css">
span.darling {
  font-size: 120%;
  color: #F0F;
}
</
style>
<?
php

$s 
= 'какой-то текст новое словообразование продолжается какой-то текст...';
$searchs = array();
$searchs[] = 'слово';
$searchs[] = 'словообразование';
$searchs[] = 'как';
$searchs[] = 'какой';

function cmp($a, $b) 
{
    if (strlen($a) >= strlen($b)) {
        return false;
    } else return true;
}
usort($searchs, "cmp");

$repl = $searchs;
function replace_span(&$item, $key) 
{
    $item = "<span class='darling'>{$item}</span>";
}
array_walk($repl, 'replace_span');

echo str_replace($searchs, $repl, $s);


глянь результат

Спустя 2 минуты, 17 секунд (2.02.2009 - 20:25) Sylex написал(а):
т.е.
PHP
usort($searchs"cmp");

имеет ключевой момент smile.gif

Спустя 1 час, 45 минут, 54 секунды (2.02.2009 - 22:11) FatCat написал(а):
Сортировка не поможет sad.gif
Операция поиска/замены происходит многократно. Каждый раз измененный текст сохраняется, и каждое последующее сопоставление происходит с уже измененным текстом.
С одним и тем же файлом текста, но с разными словами поисковых запросов, сценарий может выполняться в разные дни.

Спустя 10 минут, 36 секунд (2.02.2009 - 22:22) twin написал(а):
Вообще то хранить текст с разметкой - геморрой. Если нужно запоминать то, что выбиралось, то лучше делать это отдельно. Запоминать позиции, обрабатывать и метить на выходе.

Спустя 2 часа, 9 минут, 7 секунд (3.02.2009 - 00:31) FatCat написал(а):
Цитата (twin @ 2.02.2009 - 22:22)
Вообще то хранить текст с разметкой - геморрой.

Я скажу по секрету: разметка нужна в том числе для поисковок.
http://vesvalo.net/index.php?act=Search&CO...t=topic&trid=97 : Так вот здесь же: Двенадцать Шагов и Двенадцать Традиций АА
Вся фраза тоже должна выделяться.
После того, как слова разметились всего лишь спанами, страница поднялась в серпе как минимум на 2-3 позиции по каждому слову.


Спустя 11 минут, 50 секунд (3.02.2009 - 00:42) REANIMATOR написал(а):
Возможно это звучит глупо, но почему ты ищешь слово в тексте без пробела
т.е. можно же сделать так
PHP
$txt = str_replace(" ".$word." ","<span class='darling'>".$word."<span>",$txt);

нет?

Спустя 24 минуты, 6 секунд (3.02.2009 - 01:07) FatCat написал(а):
Цитата (REANIMATOR @ 3.02.2009 - 00:42)
почему ты ищешь слово в тексте без пробела

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

Спустя 30 минут, 4 секунды (3.02.2009 - 01:37) REANIMATOR написал(а):
а если ты каждый новый запрос будешь делать с добавлением тегов спан например:
У тебя есть "словообразование" делаешь подсветку один раз на наличие "слво"...
затем оно превращается в <span class='darling'>слово<span>образование....
делаешь ещё один поиск на наличие "словообразование" как целое слово, и потом ещё раз при условии что первичное слово уже <span class='darling'>слово<span> (2 поиска)
т.е.
PHP
$old_word = "слово";  //старое слово
$old_word_spaned = "<span class='darling'>слово<span>"; //старое слово с тегом спан
$txt = str_replace($word,"<span class='darling'>".$word."<span>",$txt);
$word = str_replace($old_word,"",$word); // тут отрезаем старое слово
$txt = str_replace($old_word.$word,"<span class='darling'>".$old_word_spaned.$word."<span>",$txt); //делаем новый поиск уже с комбинированым словом

Но при этом нужно каждый раз хранить старое слово и делать поиск дважды- один раз чистым словом другой раз вместе со старым словом...
тогда получится результат.
HTML
новое <span class='darling'><span class='darling'>слово<span>образование<span>

Спустя 41 минута, 38 секунд (3.02.2009 - 02:18) FatCat написал(а):
Цитата (REANIMATOR @ 3.02.2009 - 01:37)
Но при этом нужно каждый раз хранить старое слово и делать поиск дважды

Ох, если бы дважды.
Пример на 8
М.Битти. Преодоление созависимости
М.Битти. Преодоление созависимости
М.Битти. Преодоление созависимости
М.Битти. Преодоление созависимости
М.Битти. Преодоление созависимости
М.Битти. Преодоление созависимости
М.Битти. Преодоление созависимости
М.Битти. Преодоление созависимости


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


Как бы в саму проверку
PHP
if(stristr($txt,$word))
всунуть регулярку, отбрасывающую любые вхождения открывающего и закрывающего спанов?

Спустя 1 час, 6 минут, 40 секунд (3.02.2009 - 03:25) REANIMATOR написал(а):
хм....

если так тогда получится что если слово состоит из 10 букв, и при каждом запросе добавлять букву к слову, то слово будет иметь 10 тегов?

Спустя 9 минут, 10 секунд (3.02.2009 - 03:34) twin написал(а):
Цитата
Я скажу по секрету: разметка нужна в том числе для поисковок.

Чёто я не соображу, для каких поисковок? Если для гуглей всяких, то какая разница, хранить текст с разметкой или размечать перед выводом в поток... Просто это на много легче - запоминать позиции и обрабатывать результат в зависимости от. А там хоть спанами можно размечать, хоть флажками...

Спустя 3 часа, 40 минут, 50 секунд (3.02.2009 - 07:15) Sylex написал(а):
поддерживаю twin

Спустя 6 часов, 14 минут, 43 секунды (3.02.2009 - 13:30) FatCat написал(а):
Цитата (twin @ 3.02.2009 - 03:34)
какая разница, хранить текст с разметкой или размечать перед выводом в поток...

Увы, не выход. Там свои проблемы.

Анекдот в тему:
    Новый русский освободил джина, и джин обещает выполнить одно желание.
    - У меня есть дача на Канарах. Можно автомагистраль с Рублевки на Канары?
    - Мужик, ты офигел? Это сколько тысяч километров, это сваи в океане, а там глубина сколько километров...
    - Прости, стормозил, не подумал. Хм... Что бы тогда попросить... Ну, сделай, чтобы моя жена всегда была в хорошем настроении.
    - Хм... Мужик... А скольки полос автомагистраль ты хотел?

Спустя 53 минуты, 39 секунд (3.02.2009 - 14:23) Sylex написал(а):
FatCat
попробуй все-таки, подробно, просто и понятно объяснить что ты хочешь сделать

Спустя 1 час, 20 минут, 35 секунд (3.02.2009 - 15:44) FatCat написал(а):
Цитата (Sylex @ 3.02.2009 - 14:23)
подробно, просто и понятно объяснить что ты хочешь сделать

Пишу для нашего движка форума аналитическую систему.
Есть список кейвордов.
Система фиксирует все заходы из поисковок (по документ-реферер).
На первом этапе сверяются слова поискового запроса со списком кейвордов.
Если есть совпадения - собираем список совпавших слов (дарлингов) и идем дальше.
Второй этап - из БД берутся все сообщения форума, вошедшие в запрошенную страницу и проверяются на наличие в них дарлингов.
Дарлинги метятся спанами, сообщение и автор сообщения получают по +1 в счетчики; если запрашивался топик, то и топик получает +1 в счетчик.
При заходе следующего посетителя из поисковки весь процесс повторяется.
Плюс пишется лог (в виде топика в закрытом разделе форума) - полный текст поискового запроса и страница входа.
В итоге имеем:
- рейтинги популярности для поисковок: тем, сообщений и авторов;
- трафик по ключам;
- НЧ запросы, из которых можно собирать новые ключи для пополнения keywords.txt.

Уже есть первые результаты: благодаря "заспаниванию" ключей, пошел заметный подъем страниц в топе поисковок.
В перспективе написание "болтливого бота", который будет изредка встревать в обсуждения на форуме; бот тексты будет брать только из "дарлингованых" сообщений - тем самым, заработает и критерий "еще с сайта".

Вопрос теперь лишь в визуальном отображении. Если первый же посетитель из поисковки пришел по слову "зависимость" - визуально не видно последующих посетителей по слову "созависимость". На работу системы это не влияем, но хочется красивости. rolleyes.gif

Спустя 2 часа, 59 минут, 21 секунда (3.02.2009 - 18:43) REANIMATOR написал(а):
Вот вроде получилось...
Выдает результат типа

HTML
новое <span class='darling'><span class='darling'>слово<span>образование<span>


PHP
echo analyze_text($str,"словообразование");


function 
analyze_text($str,$needle)
{
   
$str str_replace($needle,"<span class='darling'>".$needle."</span>",$str); // тут делаем поиск и замену на наличие целых слов

  
$end_off 0// Откуда начинать искать закрывающий тег
  
$span_end_posfalse;
    if(
strpos($str,"<span class='darling'>"))
    {
           
$span_begin_pos strpos($str,"<span class='darling'>");
           
$span_end_pos strpos($str,"</span>",$end_off) ;  // Закрывающий спан (первый найденый)
           
$end_off  $span_end_pos+7// конец закрывающего спана
           
$found_text =  substr($str,$span_begin_pos,$span_end_pos-$span_begin_pos); // Текст= начало спана плюс первый закрывающий тэг
           
$number_spans =  substr_count($found_text,"<span class='darling'>") ;  // Количество спанов

          
for ($i=1;$i<=$number_spans;$i++)
          {
             
$span_end_pos strpos($str,"</span>",$end_off) +7;     // Тут ищем столько закрывающих тегов сколько и открывающих
                                                                    // И возвращаем позиция последнего закрывающего тега спан
          
}


          
$found_keword =  substr($str,$span_begin_pos,$span_end_pos-$span_begin_pos);  // тут возвращаем начинку самого внешнего спана
          
$found_keword_nospans strip_tags($found_keword); // начинка без тэгов (можно заменить на регулярку)
          
if(strpos($found_keword_nospans,$needle)) // если нужное слово существует в найденом
          
{
             
$converted_string =  str_replace($needle,"<span class='darling'>".$needle."</span>",$found_keword); // заменяем найденое
             
$str =  str_replace($found_keword,$converted_string,$str);  // возвращаем окончательный стринг
          
}

           
     }

return 
$str;
}

Спустя 36 минут, 57 секунд (3.02.2009 - 19:20) REANIMATOR написал(а):
коротко опишу принцип...
Ищем открывающий тег <span class='darling'> и один закрывающий </span>. Считаем сколько между ними есть открытых тегов, затем соответственно ищем столько же закрывающих. В результате получаем содержимое внешнего (родительного) тега. Из этого содержимого убираются теги и получается целое слово ($found_keword_nospans).

Если в этом слове найдено ключевое слово, делаем замену в (содержимое с внутреними тегами $found_keword). И в конце заменяем этот же $found_keword новым содержимым $converted_string, в оригинальном тексте $str

Спустя 1 день, 1 час, 35 минут, 50 секунд (4.02.2009 - 20:56) Alchemist написал(а):
REANIMATOR, у меня на этом примере не сработало
PHP
$str = "<span class='darling'>слово</span><span class='darling'>образование</span> lkgjb
d kjsl <span class='darling'>слово</span>sdkj s sdf jsdlkf jlkdf sldkf
s<span class='darling'>образование</span>kdjfl sd sdfjgh k"
;

echo analyze_text($str,"словообразование");


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

что-то вроде этого:
PHP
function add_key($new_key, $text)
{
    $keys = array($new_key);        // массив всех ключей найденых в тексте + новый ключ

    // собирание ключей идет в цикле, причем при каждой итерации собираются и вынимаются из текста
    // только целые ключи (не разбитые внутренними тегами), до тех пор пока не уходят все ключи
    // ожидаемое максимальное кол-во итераций: 2-3
    preg_match_all("/<span class='darling'>([^<>]+)<\/span>/is",$text,$tmp_keys);
    while(count($tmp_keys[0])){
        $keys = array_merge($keys,$tmp_keys[1]);    // добавляем свеженайденые ключи в список

        $text = str_replace($tmp_keys[0],$tmp_keys[1],$text);    // убираем найденые ключи из текста
        preg_match_all("/<span class='darling'>([^<>]+)<\/span>/is",$text,$tmp_keys);  // продолжаем поиск
    }
    $keys = array_unique($keys);
    usort($keys,'my_keys_cmp');        // сортируем ключи как хочется (в данном случае - обратно длине)

    foreach($keys as $key)            // восстанавливаем ключи в тексте
        $text = str_replace($key,"<span class='darling'>".$key."</span>",$text);
        
    return $text
;
}

// функция сортирует строки обратно пропорционально длине (длиная -> короткая)
// если строки одинаковой длины - то сортировка по алфавиту
function my_keys_cmp($a, $b)
{
    return (strlen($a) == strlen($b)) ? strcmp($a,$b) : strlen($b) - strlen($a);
}

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

также цикл вытаскивающий ключи из текста можно заменить на одну рекурсивную регулярку, но в этом случае есть ограничение - максимум один спан внутри другого спана (рекурсия возвращает только последний найденый результат для каждого уровня). Т.е. вариант
HTML
<span class='darling'>слово<span class='darling'><span class='darling'>образ</span>ование</span></span>
будет обработан правильно, а вариант
HTML
<span class='darling'><span class='darling'>слово</span><span class='darling'>образование</span></span>
потеряет один из ключей.

Спустя 2 часа, 42 минуты, 24 секунды (4.02.2009 - 23:38) REANIMATOR написал(а):

да точно. я не учёл тот факт что могут быть спаны, не один в другом...
как тут <span class='darling'>слово</span><span class='darling'>образование</span>

Спустя 1 час, 50 минут, 45 секунд (5.02.2009 - 01:29) FatCat написал(а):
Alchemist
Спасибо за идею!

Цитата (Alchemist @ 4.02.2009 - 20:56)
usort($keys,'my_keys_cmp');

Ох и поломал же я голову над этой строчкой...
Функции у меня определены в классе, и эта конструкция не работает.
И нигде про синтаксис не нашел почитать. Варианты
PHP
usort($keys,$this->'my_keys_cmp');
PHP
usort($keys,'$this->my_keys_cmp');
PHP
usort($keys,'$'.'this->my_keys_cmp');
не работают ни один.

Пришлось делать некорректно и выносить функцию my_keys_cmp за пределы класса...

Спустя 48 минут, 37 секунд (5.02.2009 - 02:18) Alchemist написал(а):
ээээ... а так не пробовал ?
$this->my_keys_cmp

Впрочем, скорее всего тоже не заработает...

Спустя 3 минуты (5.02.2009 - 02:21) kirik написал(а):
Цитата (FatCat @ 4.02.2009 - 17:29)
Пришлось делать некорректно и выносить функцию my_keys_cmp за пределы класса...

Вот так будет работать в классе -
PHP
usort($keys, array($this'my_keys_cmp'));

Про синтасис тут.

Спустя 33 минуты, 40 секунд (5.02.2009 - 02:54) FatCat написал(а):
Цитата (kirik @ 5.02.2009 - 02:21)
Про синтасис тут.

Ой-ё!!!
Что-то похожее я чувствовал, когда нужная мне информация была в книге по китайской медицине на немецком.

Спустя 5 минут, 15 секунд (5.02.2009 - 03:00) kirik написал(а):
Цитата (FatCat @ 4.02.2009 - 18:54)
Что-то похожее я чувствовал, когда нужная мне информация была в книге по китайской медицине на немецком.

biggrin.gif
На русском тоже есть там smile.gif Просто меня по дефолту перебрасывает на англицкий.

Спустя 3 часа, 54 минуты, 37 секунд (5.02.2009 - 06:54) Sylex написал(а):
Цитата (kirik @ 5.02.2009 - 05:21)
Вот так будет работать в классе -
PHP
usort($keys, array($this, 'my_keys_cmp'));

можно и так, а можно было просто заюзать static function smile.gif

Alchemist подметил верно, как я и говорил, без "переспамливания" не обойтись

просто, неужели не проще хранить список ключей, а постоянно производить их поиск?

Спустя 2 минуты, 18 секунд (5.02.2009 - 06:57) Sylex написал(а):
и еще, функции можно определять внутри методов класса

Спустя 9 часов, 5 минут, 56 секунд (5.02.2009 - 16:03) Alchemist написал(а):
Цитата (Sylex @ 5.02.2009 - 05:54)
просто, неужели не проще хранить список ключей, а постоянно производить их поиск?

ну насколько я понял, список ключей есть, но глобальный, а на каждой конкретной странице могут быть далеко не все... Но поскольку "деспаминг" все равно будет производиться в цикле (а я не вижу возможности сделать это по-другому), то, я думаю, разница производительности будет пренебрежительно мала.

Ну а скрипт я привел просто как пример имплементации алгоритма smile.gif Разумеется он может (и должен) быть улучшен. Например третью строку можно заменить на:
PHP
$keys = is_array($new_key) ? $new_key : array($new_key);
что позволит за один запуск вносить в текст сколько угодно новых ключей.

Можно улучшить регулярку, можно подумать об оптимизации выборки... Много что можно сделать... но зачем ? smile.gif

Спустя 19 минут, 9 секунд (5.02.2009 - 16:22) FatCat написал(а):
Цитата (Alchemist @ 5.02.2009 - 16:03)
разница производительности будет пренебрежительно мала.

Проверил на мегабайтном тексте с парой ключей - под денвером (не самый быстрый сервер) справился меньше чем за секунду, включая чтение и перезапись метрового файла.
В реальности же средний размер блока текста около 1 Кб, в среднем 7-10 блоков на страницу.
Опять же в среднем, скрипт будет запускаться 1-2 раза на 1000 просмотров страниц.
Я думаю, что итоговый прирост затарат ресурсов сервера будет столь мал, что будет исчисляться тысячными долями процента.

Еще раз спасибо!

Спустя 11 дней, 13 часов, 40 минут, 43 секунды (17.02.2009 - 06:02) REANIMATOR написал(а):
тут
Свернутый текст
PHP
function add_key($new_key$text)
{
    
$keys = array($new_key);        // массив всех ключей найденых в тексте + новый ключ

    // собирание ключей идет в цикле, причем при каждой итерации собираются и вынимаются из текста
    // только целые ключи (не разбитые внутренними тегами), до тех пор пока не уходят все ключи
    // ожидаемое максимальное кол-во итераций: 2-3
    
preg_match_all("/<span class='darling'>([^<>]+)<\/span>/is",$text,$tmp_keys);
    while(
count($tmp_keys[0])){
        
$keys array_merge($keys,$tmp_keys[1]);    // добавляем свеженайденые ключи в список

        
$text str_replace($tmp_keys[0],$tmp_keys[1],$text);    // убираем найденые ключи из текста
        
preg_match_all("/<span class='darling'>([^<>]+)<\/span>/is",$text,$tmp_keys);  // продолжаем поиск
    
}
    
$keys array_unique($keys);
    
usort($keys,'my_keys_cmp');        // сортируем ключи как хочется (в данном случае - обратно длине)

    
foreach($keys as $key)            // восстанавливаем ключи в тексте
        
$text str_replace($key,"<span class='darling'>".$key."</span>",$text);
        
    return 
$text;
}

// функция сортирует строки обратно пропорционально длине (длиная -> короткая)
// если строки одинаковой длины - то сортировка по алфавиту
function my_keys_cmp($a$b)
{
    return (
strlen($a) == strlen($b)) ? strcmp($a,$b) : strlen($b) - strlen($a);
}

единственная проблема это в этой строчке
PHP
$text str_replace($key,"<span class='darling'>".$key."</span>",$text);


когда скрипт сталкивается с сылкой в которой есть ключевое слово, он её портит- вставляя в href ключ. слово...
Ктото сталкивался с этой проблемой?

Объясните пожалуйста, а то я не могу понять в preg_replace() как можно сказать в патерне, что- бы замена происходила только тогда, когда нет слеша "/" например

такое не работает =\
PHP
$text preg_replace("/(^\/){$key}/","<span class='darling'>".$key."</span>",$text);

Спустя 1 месяц, 4 дня, 16 часов, 53 минуты, 24 секунды (21.03.2009 - 22:56) FatCat написал(а):
Alchemist
http://phpforum.ru/index.php?showtopic=0&v...indpost&p=69229
Спасибо реаниматору, я-то работал только с русскими словами, а он посмотрел для всех возможных.
Если ключевик окажется внутри тега, получится "каша":
HTML
<a href="<span class='darling'>php</span>forum.ru/">форум <span class='darling'>php</span>forum.ru/"></a>

Пришлось ковырять код:
PHP
foreach($keys as $key)            // восстанавливаем ключи в тексте
        
$text str_replace($key,"<span class='darling'>".$key."</span>",$text);


Не сумел уйти от вложенных циклов, но вроде бы не сильно тормозит:
PHP
foreach($keys as $key)            // восстанавливаем ключи в тексте
        
{
            
$test_tags explode($key,$text);
            
$text "";
            
$i 0;
            foreach(
$test_tags as $test_tag)
            {
                if(
$i == 0)
                {
                    
$text .= $test_tag;
                }
                else
                {
                    if( 
stristr($test_tag,">") )
                    {
                        
// Проверяем, не попали ли внутрь тега
                        
$test_tag_r explode(">",$test_tag);
                        if( 
stristr($test_tag_r[0],"<") ) // Не попали, есть открывающая скобка, дарлингуем
                        
$text .= "<span class='darling'>".$key."</span>".$test_tag;
                        else 
// Попали, возвращаем ключ и никаких дарлингов
                        
$text .= $key.$test_tag;
                    }
                    else
                    {
                        
// После ключа нет закрывающей скобки, дарлингуем:
                        
$text .= "<span class='darling'>".$key."</span>".$test_tag;
                    }
                }
                
$i++;
            }
        }

Спустя 1 день, 8 минут, 13 секунд (22.03.2009 - 23:04) Alchemist написал(а):
лучше просто замени строчку
PHP
$text = str_replace($key,"<span class='darling'>".$key."</span>",$text);

на
PHP
$text = preg_replace('/('.str_replace('/','\/',$key).')(?![^<]>)/i',"<span class='darling'>\\1</span>",$text);

Спустя 1 час, 40 минут, 32 секунды (23.03.2009 - 00:45) FatCat написал(а):
Alchemist
Ничего не понял в этой регулярке.
Но не работает.
PHP
$text "<img src='http://phpforum.ru/html/emoticons/ohmy.gif' border='0' style='vertical-align:middle' alt='ohmy.gif' />";
$key "php";
$text preg_replace('/('.str_replace('/','\/',$key).')(?![^<]>)/i',"<span class='darling'>\\1</span>",$text);
echo 
$text;


На странице получаю:
HTML
<img src='http://<span class='darling'>php</span>forum.ru/html/emoticons/ohmy.gif' border='0' style='vertical-align:middle' alt='ohmy.gif' />

Спустя 5 минут, 47 секунд (23.03.2009 - 00:50) FatCat написал(а):
Мой алгоритм:

1. Экплодим по кею, получаем массив строк. Исключив самую первую, получаем массив строки, идущих за каждым вхождением кея.

Дальше по каждой строке:

2. Если нет вхождения ">" - всё в порядке, мы не внутри тега, кей можно обрамлять спанами.

3. Если есть вхождение - "обрезаем" всё за первым вхождением и проверяем оставшуюся строку нет ли в ней "<".

4. Если есть - все в порядке, тег открылся после кея. Обрамляем спанами.
Если нет - значит мы внутри тега, возвращаем кей на место и никаких спанов.

Спустя 22 минуты, 3 секунды (23.03.2009 - 01:12) Alchemist написал(а):
не работает потому что я идиёт... у себя исправил, а тут забыл... вот правильная строка:
PHP
$text = preg_replace('/('.str_replace('/','\/',$key).')(?![^<]*>)/i',"<span class='darling'>\\1</span>",$text);


алгоритм прост - заменять все вхождения кроме тех после которых есть закрывающая тэг скобка, но перед ней нет открывающей.... фактически это не совсем верно, но чтобы улучшить регулярку надо еще подумать... на "предыдущие" условия есть ограничения.

Спустя 26 минут, 4 секунды (23.03.2009 - 01:38) FatCat написал(а):
Если я правильно понял регулярку, то по
PHP
$key "php";
$text "php - язык <i>программирования</i>";

рискуем получить:
HTML
<span class='darling'>php - язык <i></span>программирования</i>

Спустя 11 минут, 6 секунд (23.03.2009 - 01:50) Alchemist написал(а):
нет smile.gif) лишнего ничего мы не рискуем получить smile.gif

тут скорее есть риск недополучить. Например если есть фраза:
HTML
существует знак "меньше", а '>' - знак "больше"

то при ключевом слове "знак" мы получим
HTML
существует знак "меньше", а '>' - <span class="darling">знак</span> "больше"

т.е. первое вхождение будет рассмотрено как находящееся внутри тэга

Спустя 11 часов, 53 минуты (23.03.2009 - 13:43) FatCat написал(а):
Цитата (Alchemist @ 23.03.2009 - 01:50)
HTML
'>' - знак "больше"

Это нам не грозит, если для форума. Такого текста никогда не будет, ибо он отпарсится в
HTML
'&gt;' - знак "больше"


Я правильно понимаю, что регулярка рассматривает подстроку, начинающуюся кеем, и до первого вхождения закрывающей скобки? И она проверяет, не оказалось ли внутри открывающей скобки. Так?

Но тогда кей, после которого нет вообще никаких тегов, тоже не поймает?

Спустя 1 минута, 37 секунд (23.03.2009 - 13:44) FatCat написал(а):
Сорри, сейчас большой объем другой срочной работы, поэтому ни проверить в локалке, ни толком вникнуть нет ни времени ни мозгов... Может завтра разгребу дела и гляну повнимательнее.
В любом случае громадное спасибо.

Спустя 9 минут, 3 секунды (23.03.2009 - 13:53) Alchemist написал(а):
Цитата (FatCat)
Я правильно понимаю, что регулярка рассматривает подстроку, начинающуюся кеем, и до первого вхождения закрывающей скобки? И она проверяет, не оказалось ли внутри открывающей скобки. Так?

нет, не правильно. Регулярка находит ключ, после чего проверяет есть ли после него закрывающая тэг скобка (без открываюющей). Если есть, то этот найденый ключ отбрасывается. Если после ключа ничего нет - соответственно нет и закрывающей скобки - т.е. ключ подходит.

(?!...) - это отрицательное утверждение... типа условия IF NOT.

не за что smile.gif


_____________
Бесплатному сыру в дырки не заглядывают...
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2025 Invision Power Services, Inc.