Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум Регулярные Выражения

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Помогите написать функцию транслита
 
 автор: Visavi   (19.12.2008 в 12:56)   письмо автору
 
 

Не знаю как лучше сделать, вот у меня есть например функция translit(); она заменяет все латинские символы на русские
Нужно сделать чтобы в этой строке
"Privet [b]drug[/ b] moya fotka <img src="....">"

не изменяло то что начинается с этих знаков: [ и < и кончается этими: ] и >

то есть чтобы получилось
"Привет [b]друг[/ b] моя фотка <img src="....">"


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

  Ответить  
 
 автор: xx77   (19.12.2008 в 18:54)   письмо автору
 
   для: Visavi   (19.12.2008 в 12:56)
 

тут на php особо ничего такого супер-пупер и нельзя поделать,
только что-нибудь примерно такое
<pre><?
$razy 
0;
function 
tr_pr($match) {
global 
$razy;
$razy++;
return (!isset(
$match[1]))
 ? 
translit($match[0]): $match[0];
}

$text ' slovo  slova <img src="..."/>
YIyoshkarOla
 slovischi <img src="..."/> [v<img src="..."/>]
[zzzzzzzzz[
ppp][bbbbb[[[[[slovo>
[test>
[
'
;
echo 
preg_replace_callback('#([<\[])/?\w+[^>\]]*[>\]]|[^<\[]+#''tr_pr'$text);
echo 
"\n$razy\n";
$razy 0;

echo 
preg_replace_callback('#</?\w+[^>]*(>)|\[/?\w+(\])|.[^<\[]+#''tr_pr'$text);
echo 
"\n$razy\n";
$razy 0;

echo 
preg_replace_callback('#(?:<[^>]+(>)|\[/?\w+(\]))+|[^<\[]+#''tr_pr'$text);
echo 
"\n$razy\n";

## или просто разбивать строку и прогонять в цикле
print_r(preg_split("#((?:[<\[]/?\w+.*?[>\]])+)#"$text, -1
PREG_SPLIT_DELIM_CAPTURE));
?>
точно сказать какое выражение быстрее не скажу , так по логике вроде самое первое как самое неточное ,) даже точно скажу что все выражения медленные
Но нужно более-менее точно сравнить время , и пробовать оптимизировать.
С циклами после preg_split тоже бывает намного медленнее работает.
Многое ещё зависит от того какой конкретно будет обрабатываемый текст
Если есть возможность делать одновременно транслитирование и например вставку этих <img>
которые откуда-то тоже взялись , то иногда выгоднее так делать, меньше разворотов одного и того-же текста - меньше времени , я так думаю

//upd:

Хотя ещё один вариант выражения для preg_replace_callback()
типа
'#([^<\[]*)((?>(?:\[/?\w+\]|<[^>]+>|$)\s*)+)#'
за одно совпадение шаблона выберет сразу и то что нужно
, и что не нужно обрабатывать , меньше прохождений но тоже не str_replace

  Ответить  
 
 автор: Visavi   (20.12.2008 в 00:06)   письмо автору
 
   для: xx77   (19.12.2008 в 18:54)
 

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

все три нормально работают и по скорости примерно одинаковы

только первое выражение не обрабатывает к примеру [privet>
а второе и третье наоборот обрабатывают [url=http://....]...

а вот в первое выражение можно воткнуть чтобы не обрабатывало &amp; &gt; &lt; и подобные?

  Ответить  
 
 автор: xx77   (20.12.2008 в 03:08)   письмо автору
 
   для: Visavi   (20.12.2008 в 00:06)
 

можно, но такое выражение будет совсем медленное :)
и возможно даже медленнее чем второе preg_replace() внутри callback-функции
<?
 $razy 
0;
function 
tr_pr($match) {
global 
$razy;
$razy++;
return (isset(
$match[1]))
 ? 
translit($match[0]): $match[0];
}

$text ' slovo  slova <img src="..."/>
&amp; ili &lt; ili &amp;amp;  \'""\'\'"" ili &amp;gt;
[u rl=http://test]test[/u rl]
[test>x][u rl]http://testtest[/u rl]
[
'
;


$reg '~(?:[&<\[] #первый символ.
# найдя его прокручивается всё возможное дальше
# с приоритетом тому чтобы включить как можно большую строку
(?(?<=<) # здесь условная захватывающая подмаска в условиях которой стоит
# проверка был-ли символ < перед ней , чаще там ставят просто цифру.

# если да:
[^>]*>
| #или ещё проверка
(?(?<=&) [a-z]{2,5};
| #или ещё 
(?:url(?:\=http://|\]http://)[^\[]+\[/url\]
|/?\w+[^\]]*\])
)
)\s*)+
# глобальное или
|([^&<\[]+.??)+? # нежадно проверяет после каждого символа нет-ли [&<\[]

~xs'
// x  можно убрать удалив все комментарии и пробелы и \n из $reg


echo preg_replace_callback($reg'tr_pr'$text);
echo 
"\n$razy\n";
$razy 0;

echo 
preg_replace_callback('#(?:[<\[](?:(?<=<)[^>]*>|(?:url(?:\=http://|\]http://)[^\[]+\[/url\])|/?\w+[^\]]*\])\s*)+|([^<\[]+.??)+?#''tr_pr'$text);
echo 
"\n$razy\n";
добавил пробелы в тегах [url] $text

Пересмотреть весь процесс обработки текста с самого его появления похоже точно не помешало-бы, чтобы избежать таких выражений, пусть даже при небольших объёмах текста

// в тех первых шаблонах просто было \[\w+\] которое непропускало [url=

  Ответить  
 
 автор: Visavi   (20.12.2008 в 19:17)   письмо автору
 
   для: xx77   (20.12.2008 в 03:08)
 

Спасибо вам, что-нибудь придумаю

  Ответить  
 
 автор: xx77   (20.12.2008 в 20:33)   письмо автору
 
   для: Visavi   (20.12.2008 в 19:17)
 

тут насчёт этого
([^&<\[]+.??)+? # нежадно проверяет после каждого символа нет-ли [&<\[]

что-то сомнения одолели :) возможно это не дало того что некоторые &<[ включались , а не просто пропускались
можно попробовать просто ([^&<\[]+) и посмотреть какое получится число вызовов функции.
хотя важнее время выполнения.
проверить можно хотя-бы с текстом побольше , вызвав preg_replace_callback() с одним выражением несколько раз

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования