Как НЕ учитывать регистр в регулярных выражениях (в Drupal)

Главные вкладки

Аватар пользователя Vitalik Vitalik 17 сентября 2008 в 14:27

Здравствуйте!

Возникла следующая проблема.

Необходимо в строке выделить жирным определенный текст (как в результатах поиска).

Например, было: "Просто какой-то текст", надо выделить "Какой", то есть получить: "Просто какой-то текст" (при чем, как видно, регистр не имеет значения)

Пробовал это делать регулярными выражениями, разными функциями, при чем использовал разные кодировки текста (и windows-1251, и utf-8), но ничего не получается.. Sad
При чем еще такая особенность: до выполнения drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); всё работает, а после - резко не хочет..

Добавлено:

Гм.. Сейчас вот попробовал упорядоченно испытать все возможные комбинации функций и кодировок.
И получилось следующее..

Примечание
Исходный код в кодировке windows-1251, для конвертации в utf-8 используется функция
function w($value) { return iconv("windows-1251", "utf-8", $value); }
Отображение идет в кодировке utf-8

index.php
До и после выполнения drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); вставлялся следующий код:

echo preg_replace(w('/(Какой)/'), "(\\1)", w('Просто какой-то текст'))."<br/>";
echo w(preg_replace(('/(Какой)/'), "(\\1)", ('Просто какой-то текст'))."<br/>");
echo preg_replace(w('/(Какой)/i'), "(\\1)", w('Просто какой-то текст'))."<br/>";
echo w(preg_replace(('/(Какой)/i'), "(\\1)", ('Просто какой-то текст'))."<br/>");
echo ereg_replace(w('(Какой)'), "(\\1)", w('Просто какой-то текст'))."<br/>";
echo w(ereg_replace(('(Какой)'), "(\\1)", ('Просто какой-то текст'))."<br/>");
echo eregi_replace(w('(Какой)'), "(\\1)", w('Просто какой-то текст'))."<br/>";
echo w(eregi_replace(('(Какой)'), "(\\1)", ('Просто какой-то текст'))."<br/>");
echo mb_ereg_replace(w('(Какой)'), "(\\1)", w('Просто какой-то текст'))."<br/>";
echo w(mb_ereg_replace(('(Какой)'), "(\\1)", ('Просто какой-то текст'))."<br/>");
echo mb_eregi_replace(w('(Какой)'), "(\\1)", w('Просто какой-то текст'))."<br/>";
echo w(mb_eregi_replace(('(Какой)'), "(\\1)", ('Просто какой-то текст'))."<br/>");

При этом до выполнения drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); выполнились успешно строки:

echo w(preg_replace(('/(Какой)/i'), "(\\1)", ('Просто какой-то текст'))."<br/>");
echo w(eregi_replace(('(Какой)'), "(\\1)", ('Просто какой-то текст'))."<br/>");
echo w(mb_eregi_replace(('(Какой)'), "(\\1)", ('Просто какой-то текст'))."<br/>");

А после выполнения drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL); только одна:

echo w(mb_eregi_replace(('(Какой)'), "(\\1)", ('Просто какой-то текст'))."<br/>");

Вывод:

Чтобы решить проблему, работать нужно ТОЛЬКО со строками в кодировке windows-1251 (а не utf-8).
То есть, если строки всё-таки в кодировке utf-8, то нужно временно перевести их в windows-1251
При чем чтобы всё заработало в Друпал, необходимо с этими windows-1251 строками работать ТОЛЬКО с помощью функций mb_eregi_replace.

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

Комментарии

Аватар пользователя axel axel 17 сентября 2008 в 14:40

Стоит помнить, что регулярные выражения Perl (функции preg*) и POSIX (функции ereg*) отличаются синтаксисом. Например для preg* нужно в конце выражения ставить модификатор i:

'/регвыр/i'

Остальные модификаторы - http://ru2.php.net/manual/ru/reference.pcre.pattern.modifiers.php

Также следует помнить, что только ereg-функции имеют дубли в mbstring, а preg-функции - не имеют. Вместо этого в Perl-регвырах можно использовать модификатор u указывающий на необходимость работы с юникодом.

Аватар пользователя Vitalik Vitalik 17 сентября 2008 в 16:08

glu2006 wrote:
А можно посмотреть пример задачи для которой пришлось так извращаться?

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

Например, искали слово "книга". Результат нужно отобразить в виде:

Quote:
Найдено:
- Самая лучшая книга такая-то
- У кого есть книга Лукьяненко?
- Книга всем книгам книга

Аватар пользователя Vitalik Vitalik 17 сентября 2008 в 16:02

axel, большое спасибо за быстрый ответ!

Отличия ereg и preg я учел, модификатор i для preg ставил, mb-функции для ereg пробовал.
А вот про модификатор u не догадался Smile

И это получается еще один рабочий вариант:

echo preg_replace(w('/(Какой)/iu'), "(\\1)", w('Просто какой-то текст'))."<br/>";

То есть работать можно с текстом в кодировке utf-8 и всё работает замечательно!

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

Аватар пользователя Nikit Nikit 14 октября 2008 в 3:54

Вот такая функция получилась с помощью preg_replace, w() убрал т.к. уже не нужен этот вызов:

function highlight($searchItem, $text) {
  if (!empty($searchItem) && !empty($text)) {
    return preg_replace('/('.$searchItem.')/iu',
      "<span class='highlight'>".$searchItem."</span>", $text);
  }
  else {
    return $text;
  }
}

Теперь другая проблемка, в $text найденное заменяется на $searchItem с учетом регистра, а вот как сделать, чтобы регистр оставался таким же, какой он в $text, то есть:
highlight('тЕст', 'Тут тестовый текст');
на выходе: Тут тЕстовый текст, а нужно чтобы регистр оставался тем же...
Не критичная проблемка, но всё таки...

Аватар пользователя Gairon Gairon 11 июля 2009 в 19:55

Решение - использовать карманы, то есть вместо

<?php
return preg_replace('/('.$searchItem.')/iu'
      
"<span class='highlight'>".$searchItem."</span>"$text);
?>

написать

<?php
return preg_replace('/('.$searchItem.')/iu'
      
"<span class='highlight'>$1</span>"$text);
?>