Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Тексты > Правильность регулярки


Автор: MoLeX 7.2.2012, 07:08
Добрый день. 
Для того, чтобы избавится от повторяющих пробелов и управляющих символов (\r, \n, \t) использую следующее
Код

$html = "<!DOCTYPE html>
<html>    <head>
<title>Title</title>
</head>
<body>
              <div>   test&nbsp;&nbsp;&nbsp;&nbsp;test   </div>
</body>
</html>";

$html = preg_replace( "/[[:cntrl:]]/", "", $html );
$html = preg_replace("/ +/i", " ", $html);

echo $html;
/*
<!DOCTYPE html><html> <head><title>Title</title></head><body> <div> test&nbsp;&nbsp;&nbsp;&nbsp;test </div></body></html>
*/


Верна ли данная конструкция? Сильно ли она прожорлива и как её можно оптимизировать

Автор: ayax2005 7.2.2012, 08:10
А зачем вообще это нужно? Контролировать пробелы правильнее на шаге тформирования контента в цмске, это сэкономит ресурсы при отображении; а управляющие символы чем помешали - ума не преложу.
Конечно, регулярка на боле-менее объёмный документ потребует времени на обработку.

Автор: MoLeX 7.2.2012, 08:34
ayax2005, хотя бы для ответа AJAX.
Ответ такого вида уже не обработается
Код

{"status":false, "error":"", "content":"<br>9
text
     text
text"}


Добавлено через 1 минуту и 8 секунд
Ответ генерируется из шаблона, и его лучше писать понятным образом для редактирования
Код

<div id="mydiv">
    <span>span</span>
    <p>Text</p>
</div>


Добавлено через 3 минуты и 57 секунд
потом предпочитаю отдавать контент как можно сильнее ужатый - вырезаны лишние пробелы, переводы строк. Это позволяет отдавать контент немного быстрее

Автор: ksnk 7.2.2012, 09:04
MoLeX, При кодировании строки в Json, как символ "\n" должен переводится в последовательность символов '\n'. Так что - что-то неправильное с генерацией данных для Ajax - надо бы разобратся  smile.
К тому-же удалять служебные символы и пробелы из изображения строки может оказаться неправильно. Вдруг строка обязана содержать 5 пробелов?

Автор: MoLeX 7.2.2012, 09:06
Цитата(ksnk @  7.2.2012,  09:04 Найти цитируемый пост)
К тому-же удалять служебные символы и пробелы из изображения строки может оказаться неправильно. Вдруг строка обязана содержать 5 пробелов? 

служебные не нужны, а для пробела есть &nbsp;

Добавлено через 1 минуту и 9 секунд
Цитата(ksnk @  7.2.2012,  09:04 Найти цитируемый пост)
К тому-же удалять служебные символы и пробелы из изображения строки может оказаться неправильно. Вдруг строка обязана содержать 5 пробелов? 

служебные не нужны, а для пробела есть &nbsp;

Автор: ksnk 7.2.2012, 09:30
Кстати, для выкидывания сдвоенных пробелов и пробельных символов лучше использовать такую регулярку
Код

$html = preg_replace("/\s\s+/", " ", $html);

P.S. i - не нужен...

Автор: krundetz 7.2.2012, 13:08
MoLeX, насчет прожорливости надо тестировать, вот вариант для сравнения вместо твоей первой
Код

$html = str_replace(array("\n", "\t", "\r"), " ", $html );

попробуй также вот эту, если я правильно помню то она тебе заменить обе твои
Код
$html = preg_replace("/\s+/i", " ", $html);

Цитата(ksnk @  7.2.2012,  09:30 Найти цитируемый пост)
/\s\s+/

зачем два раза спецсимвол указал?

Автор: ksnk 7.2.2012, 13:19
krundetz, После такой замены правильный json
Код

{text:"<br>9
text
     text
text"}

превращается в неправильный
Код

{text:"<br>9texttexttext"}

Автор: krundetz 7.2.2012, 13:24
Цитата(ksnk @  7.2.2012,  13:19 Найти цитируемый пост)
превращается в неправильный

хм, счас проверю руками

Добавлено через 4 минуты и 31 секунду
протестировал, получил следующие
Код

{text:"<br>9 text text text"}


Добавлено через 7 минут и 5 секунд
сообразил ты про первый вариант, да там косяк сейчас поправлю, надо "" поменять на " "

Добавлено через 8 минут и 54 секунды
исправил

Автор: ksnk 7.2.2012, 13:38
Цитата(krundetz @  7.2.2012,  13:08 Найти цитируемый пост)
зачем два раза спецсимвол указал?

Если указать один - заменен будет каждый пробел. Если два - только нужная сдвоенная комбинация пробельных символов

Автор: krundetz 7.2.2012, 14:57
Цитата(ksnk @  7.2.2012,  13:38 Найти цитируемый пост)
Если указать один - заменен будет каждый пробел. Если два - только нужная сдвоенная комбинация пробельных символов 

тогда, в тексте с одиночным вхождением символов "\n" "\t" замена тоже не произойдет

Автор: ksnk 7.2.2012, 15:22
Цитата(krundetz @  7.2.2012,  14:57 Найти цитируемый пост)
тогда, в тексте с одиночным вхождением символов "\n" "\t" замена тоже не произойдет 

Да. дествительно... Вот что значит - под Виндой сижу  smile У меня перевод строки - два символа...
Тогда так
Код

$html = preg_replace('/(?:\s\s+|[\n\r\t])/', " ", $html);

Хотя тут уже сложность регулярки может сожрать всю оптимальность замен  smile 
В общем - тестировать надо.

Автор: krundetz 8.2.2012, 00:22
ksnk, а такая конструкция:
Код

\s+

разве не говорит что количество символов 1 или больше (то есть и 2)? А то что она заменяет пробел на пробел так ничего страшного. Цикл поиска всего с двумя условиями получается, а не с 7 как у тебя в последнем варианте. Что по идее должно работать быстрее. Хотя я за тест.

Кстати как тестировать будем?

Автор: ksnk 8.2.2012, 01:10
Цитата(krundetz @  8.2.2012,  00:22 Найти цитируемый пост)
Кстати как тестировать будем?

Моя проигрывает примерно в 1,5 раза. Можно не тестировать. Накладные расходы на сложность регулярки сильно больше накладных расходов на лишние реплейсы... Хотя мой первоначальный вариант немного выигрывает одинокому \s  smile 
Код


// so let's go generate

function mkt(){
    static $tm ; 
    $ttm = $tm ;$tm=microtime(true) ;
    return $tm-$ttm ;
} 
// char per word 2-10
// word per line 5-7
// spaces between words 1-8

function genWord($len){
    static $charbase='abcdefghijklmnopqrstuvwxyz';
    $result='';
    for($i=0;$i<$len;$i++){
        $result.=$charbase[rand(0,strlen($charbase)-1)];
    }
    return $result;
}

function genLine($words){
    $result='';
    for($i=0;$i<$words-1;$i++){
        $result.=genWord(rand(2,10)).str_pad(' ',rand(1,8));
    }
    return $result.genWord(rand(2,10));
}

function genLines($lines){
    $result='';
    for($i=0;$i<$lines;$i++){
        $result.=genLine(rand(5,7))."\r\n";
    }
    return $result;
}

//echo genLines (4);

// so let's test it


foreach(array(4,40,4000) as $xxx){
    $test=genLines ($xxx);
    printf('strlen - %s ',strlen($test));
    mkt(); 
    $preg='/\s+/';
    for ($i=0;$i<10;$i++){
        preg_replace($preg,' ',$test,-1,$repl);
    }
    printf(' reg "%s" - step %f:2:3:3 (%d replacement)',htmlspecialchars($preg),mkt(),$repl);
    
    $preg='/(?:\s\s+|[\n\r\t])/';
    for ($i=0;$i<10;$i++){
        preg_replace($preg,' ',$test,-1,$repl);
    }
    printf(' reg "%s" - step %f:2:3:3 (%d replacement)',htmlspecialchars($preg),mkt(),$repl);
    
    $preg='/\s\s+/';
    for ($i=0;$i<10;$i++){
        preg_replace($preg,' ',$test,-1,$repl);
    }
    printf(' reg "%s" - step %f:2:3:3 (%d replacement)<br>',htmlspecialchars($preg),mkt(),$repl);
}


Добавлено @ 01:11
mkt - функция, вычисляющая время между вызовами mkt

Автор: Gold Dragon 8.2.2012, 07:49
результат:
Цитата

strlen - 238
- reg "/\s+/" - step 0.000274:2:3:3 (23 replacement) 
- reg "/(?:\s\s+|[\n\r\t])/" - step 0.000331:2:3:3 (21 replacement) 
- reg "/\s\s+/" - step 0.000255:2:3:3 (21 replacement)

strlen - 2234
- reg "/\s+/" - step 0.001425:2:3:3 (230 replacement)
- reg "/(?:\s\s+|[\n\r\t])/" - step 0.001975:2:3:3 (204 replacement)
- reg "/\s\s+/" - step 0.001380:2:3:3 (204 replacement)

strlen - 242296
- reg "/\s+/" - step 0.154205:2:3:3 (24062 replacement)
- reg "/(?:\s\s+|[\n\r\t])/" - step 0.214269:2:3:3 (21493 replacement)
- reg "/\s\s+/" - step 0.152633:2:3:3 (21493 replacement)

Автор: krundetz 8.2.2012, 11:25
Gold Dragon, у тебя strlen длина строки в которой встречаются искомые спецсимволы? или количество спецсимволов в строке?

Автор: MoLeX 8.2.2012, 11:37
надо все осмыслить

Автор: Gold Dragon 8.2.2012, 12:44
krundetz, это код ksnk smileкоторый выше

Автор: krundetz 8.2.2012, 13:27
Цитата(Gold Dragon @  8.2.2012,  12:44 Найти цитируемый пост)
krundetz, это код ksnk smileкоторый выше 

понял, а исходные данные какие брал?

Автор: MoLeX 8.2.2012, 13:31
krundetz, они там генерируются) 

Автор: krundetz 9.2.2012, 09:02
Цитата(MoLeX @  8.2.2012,  13:31 Найти цитируемый пост)
krundetz, они там генерируются)  

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

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)