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


Автор: bars80080 9.6.2010, 17:54
подсобите регулярным выражением

надо заменить все 
\n
на
</p>\n<p>

за исключением тех \n, что находятся внутри тэгов [ list] ... \n ... [ /list] (пробелы в тэгах поставлены, чтобы тэги не были обработаны на этом форуме)

то есть при парсе bb-кодов меняем все переводы строк на разделение абзацев, за исключением тех переводов, что внутри списков

спасибо

Автор: ksnk 9.6.2010, 18:26
Одним регулярным не обойтись ;)
Код

   // заменяем все теги и записываем их в массив
$text=" Hello! world 

Hello! [ b]world [/b]
Hello! [ b]world [/b]
Hello! [ b]world [/b]
Hello! [ b]world [/b]
";
echo '<hr>'.htmlspecialchars($text);

$currentTAG=0;
$store=array();

$text=preg_replace_callback('#[(\w+?)].*?[/\\1]#im',create_function('$m','global $store,$currentTAG;
    $store[$currentTAG]=$m[0]; 
    return "@@".($currentTAG++)."@@";'),$text);
echo '<hr>'.htmlspecialchars($text);

$text="<p>".implode("</p>\n<p>",explode("\n",trim($text)))."</p>";

$text=preg_replace_callback('/@@(\d+)@@/m',create_function('$m','global $store;
    return $store[$m[1]];'),$text);
echo '<hr>'.htmlspecialchars($text);



Добавлено через 1 минуту и 29 секунд
bb коды нужно без пробелов бить, а то форум глючит ;)

Автор: s0lman 9.6.2010, 18:40
А почему нельзя негативным предпросмотром вперед проверить закрывающийся list?
Где-то так
Код

preg_replace('/\\n(?!.*\[\/list\])/iU', '</p>\n<p>', '[list] sasds \n sdsd [/list] \n ');


Добавлено через 1 минуту и 45 секунд
упс, понял)

Автор: SickFxck 9.6.2010, 18:45
Я бы советовал использовать нормальный BB-парсер. Например, xBB

Автор: bars80080 9.6.2010, 18:58
Цитата(SickFxck @  9.6.2010,  18:45 Найти цитируемый пост)
Я бы советовал использовать нормальный BB-парсер. Например, xBB 

не интересно


ksnk, честно говоря, интересует только один тэг и именно в такой постановке.

Автор: ksnk 9.6.2010, 19:03
Цитата(bars80080 @  9.6.2010,  18:58 Найти цитируемый пост)
ksnk, честно говоря, интересует только один тэг и именно в такой постановке. 

ну тогда достаточно заменить первую регулярку на
Код

 '#['.'list].*?[/list]#im'

а так все то-же самое. Заменить теги на плейсхолдеры, поменять и вернуть все взад... Кстати, сама замена делается совсем даже не регулярками ;)

Автор: SickFxck 9.6.2010, 22:09
Цитата(bars80080 @  9.6.2010,  18:58 Найти цитируемый пост)
ksnk, честно говоря, интересует только один тэг и именно в такой постановке. 

— действительно, там разбираться придётся. Лучше уж делать работу инструментом, не предназначенным для задачи. Зато разбираться не нужно.

Автор: bars80080 9.6.2010, 23:46
Цитата(SickFxck @  9.6.2010,  22:09 Найти цитируемый пост)
действительно, там разбираться придётся. Лучше уж делать работу инструментом, не предназначенным для задачи. Зато разбираться не нужно. 

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

Автор: bars80080 10.6.2010, 11:35
что-то не катит этот метод:

Код

    $text = preg_replace_callback('#[list].*?[/list]#im',create_function('$m','global $store,$currentTAG;
        $store[$currentTAG]=$m[0];
        return "@@".($currentTAG++)."@@";'),$text);
    //echo '<hr>'.htmlspecialchars($text);
    $text = '<p>'.implode("</p>\n<p>", explode("\n",trim($text)))."</p>";
    $text = preg_replace_callback('/@@(\d+)@@/m',create_function('$m','global $store;
        return $store[$m[1]];'),$text);

во-первых, он всё равно запихивает </p><p> внутрь [ list]. так ещё и покушается на другие тэги, делая из [ align] к примеру [ a@@gn]

Автор: ksnk 10.6.2010, 11:47
Цитата(ksnk @  9.6.2010,  18:26 Найти цитируемый пост)
$currentTAG=0;
$store=array();

эти строчки есть?
Если они где-то в глубине разнообразных инклюдов, то можно написать так
Код

$GLOBALS['currentTAG']=0;
$GLOBALS['store']=array();


Цитата(bars80080 @  10.6.2010,  11:35 Найти цитируемый пост)
так ещё и покушается на другие тэги, делая из [ align] к примеру [ a@@gn] 
Йа тормоз smile регулярку нужно было делать такой
Код

'#\[list\].*?\[/list\]#im'



Автор: bars80080 10.6.2010, 13:43
Цитата(ksnk @  10.6.2010,  11:47 Найти цитируемый пост)
currentTAG=0;
$store=array();

эти строчки есть?
Если они где-то в глубине разнообразных инклюдов, то можно написать так
код PHP
1:
2:
$GLOBALS['currentTAG']=0;
$GLOBALS['store']=array();

есть, и так и так проверил, всё равно вставляет </p><p> внутрь [ list]


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

Код

    $s1 = explode('[list', $text);
    $s1c = count($s1);
    $s1[0] = str_replace("\n", "</p>\n<p>", $s1[0]);
    for($i = 1; $i < $s1c; $i++) {
        $s2 = explode('[/list]', $s1[$i]);
        $s2c = count($s2);
        for($j = 1; $j < $s2c; $j++) { $s2[$j] = str_replace("\n", "</p>\n<p>", $s2[$j]); }
        $s1[$i] = implode('[/list]', $s2);
    }
    $text = implode('[list', $s1);

Автор: MoLeX 10.6.2010, 13:57
Цитата(bars80080 @  10.6.2010,  13:43 Найти цитируемый пост)
и он получился настолько краткий

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

Добавлено через 30 секунд
для малых объемов он хорошо)

Автор: bars80080 10.6.2010, 14:30
Цитата(MoLeX @  10.6.2010,  13:57 Найти цитируемый пост)
да краткий, но меня пугают вложенные циклы. Ведь если текст очень большой то сколько это времени надо

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

итого, суммарное количество итераций в нормальном состоянии даже для больших текстов - 10.
вроде не много

Автор: ksnk 10.6.2010, 15:14
bars80080, для больших(>100к) текстов регулярки начинают сильно тормозить, так что цикл - не так и плохо. Вот только маленькие-большие буквы в этих [ LiSt]'ах встречаются? 

Автор: bars80080 10.6.2010, 16:02
Цитата(ksnk @  10.6.2010,  15:14 Найти цитируемый пост)
Вот только маленькие-большие буквы в этих [ LiSt]'ах встречаются? 

нет, я их сам вставляю

объём текста - максимум 64к, при больших объёмах он будет резаться

Добавлено через 1 минуту и 57 секунд
минусы зачем-то поставили. наверное, в моих постах кроется ошибка, настолько очевидная, что её не стоит даже озвучивать

Автор: NLspieler 11.6.2010, 16:49
ksnk абсолютно прав.
Нужно найти все 
Код

[list]...[/list]
 и заменить все их на специальные текстовые ссылки на массив,
в который сохранить их содержимое.
Потом произвести замену \n при помощи str_replace. 
После чего заменить текстовые метки обратно на сохраненные листы из массива.

Первая сложность, которая совсем и не сложность - это найти эти самые листы при помощи регулярки.
Но тут возникает вопрос, может ли тег list иметь атрибуты и если да, то в каком формате.
Если нет, то регулярка будет выглядеть намного проще.

Вторая проблема: Возможны ли такие случаи, что в теге лист могут находиться другие теги лист? И если да, то что делать в таких случаях?
(кстати только тогда подадобится цикл - всего одни, иначе же никакие циклы совсем не нужны)


Автор: bars80080 11.6.2010, 17:48
Цитата(NLspieler @  11.6.2010,  16:49 Найти цитируемый пост)
Но тут возникает вопрос, может ли тег list иметь атрибуты и если да, то в каком формате.
да, может. то есть либо [ list], либо [ list=(1|a|I)]

Цитата(NLspieler @  11.6.2010,  16:49 Найти цитируемый пост)
Возможны ли такие случаи, что в теге лист могут находиться другие теги лист?

вообще, нет. внутренний цикл - это ошибка, в результате текст как-то поедет, но это уже проблема пользователей

Автор: NLspieler 11.6.2010, 20:44
Вот что получилось, вроде работает.
Правда без массивов обойтись не получилось
Код

<?php

$text = "hallo hallo \n [list atr=111]slkd
jflksjdf\nsdfsdf[/list] wei
ter [list]klsdf[/list]dfgdfgdfg
dfgdfgdfgdfg" ;

echo n_p ($text) ;

function n_p ($text)
{
    //Убираем переводы каретки, которые не нужны, но будут мешать
    $text = str_replace ("\r" , '' , $text) ; 
    
    //Ищем листы и сохраняем в массив
    $reg = '|\[list.*\].*\[/list\]|isU' ;
    preg_match_all ($reg , $text , $matches) ;
    $lists = $matches[0] ;
    
    //Меняем листы на метки
    foreach ($lists as $key => $value)
    {
        $text = str_replace ($value , '||#|' . $key . '|#||' , $text) ;
    }

    //Теперь заменяем \n на </p>\n<p>
    $text = str_replace ("\n" , '</p>' . "\n" . '<p>' , $text) ;

    //Производим обратную замену меток на соответствующие листы
    foreach ($lists as $key => $value)
    {
        $text = str_replace ('||#|' . $key . '|#||' , $value , $text) ;
    }

    return $text ;
}
?>

Автор: Kano 18.6.2010, 13:35
NLspieler, надо ли говорить, что код некорректен? Зачем писать ###код? Если в тексте будет "||#|0|#||"?

Автор: bars80080 18.6.2010, 16:27
Цитата(Kano @  18.6.2010,  13:35 Найти цитируемый пост)
Если в тексте будет "||#|0|#||"?

значит, использовать другую комбинацию.

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

Автор: bars80080 18.6.2010, 22:08
Цитата(Kano @  18.6.2010,  13:35 Найти цитируемый пост)
надо ли говорить, что код некорректен?

кстати, так и не услышал, почему код не корректен?

Автор: SickFxck 18.6.2010, 22:35
Цитата(bars80080 @  18.6.2010,  22:08 Найти цитируемый пост)
кстати, так и не услышал, почему код не корректен? 

— ожидаемые данные не совпадают с фактическими. Непонятно, да?

Автор: bars80080 18.6.2010, 23:49
Цитата(SickFxck @  18.6.2010,  22:35 Найти цитируемый пост)
— ожидаемые данные не совпадают с фактическими. Непонятно, да?

в смысле не совпадает? вводим правило: пользователю запрещено использовать комбинацию "||#|0|#||"
всё, ожидаемый результат совпадает с фактическим.

Автор: SickFxck 19.6.2010, 00:33
Цитата(bars80080 @  18.6.2010,  23:49 Найти цитируемый пост)
в смысле не совпадает? вводим правило: пользователю запрещено использовать комбинацию "||#|0|#||"
всё, ожидаемый результат совпадает с фактическим.

— не можем справиться с проблемой — сделаем вид, что её нет! smile

P.S. Я тебе даже подскажу: экранирование надо применять, ага.

Автор: bars80080 19.6.2010, 10:24
Цитата(SickFxck @  19.6.2010,  00:33 Найти цитируемый пост)
не можем справиться с проблемой — сделаем вид, что её нет!

с какой проблемой не справились?

и так и не услышал, почему код не корректен?

Цитата(SickFxck @  19.6.2010,  00:33 Найти цитируемый пост)
Я тебе даже подскажу: экранирование надо применять, ага.

зачем?

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