Вопрос по регулярному выражению

12
M
На сайте с 20.08.2004
Offline
376
1144

Подскажите в какую сторону копать.

есть задача "/\[spoiler\](.*?)\[\/spoiler\]/is" заменять на '<div class="spoiler-header">Спойлер: показать</div><div class="spoiler-block">$1</div>'

функция $text = preg_replace($search, $replace, $text) отлично справляется если нет вложенности.

а вот такая констукция [spoiler]а тут спойлер в*спойлере[spoiler]текст в*спойлере[/spoiler][/spoiler]

уже не работает!

подскажите как грамотно сделать!

в будущем надо будет сделать обратное дейсвие, полученный хтмл код преобразовать в bb

спасибо

отец сыночка, лапочки дочки и еще одного сыночка
siv1987
На сайте с 02.04.2009
Offline
427
#1

1. Запретить вложенность ббкодов.

2. Написать рекурсивное регулярное выражение.

3. Выполнить циклическую замену. Проходите один раз текст, проходите второй до тех пор пока не найдутся совпадения.

M
На сайте с 20.08.2004
Offline
376
#2
siv1987:
1. Запретить вложенность ббкодов.
2. Написать рекурсивное регулярное выражение.
3. Выполнить циклическую замену. Проходите один раз текст, проходите второй до тех пор пока не найдутся совпадения.

ну тогда вы забыли и как минимум 4 вариант, тупо менять

[spoiler] -> <div class="spoiler-header">Спойлер: показать</div><div class="spoiler-block">

а

[/spoiler] -> </div>

по пунктам.

1. не актуально.

2. думаю на этот вопрос я и хотел бы получить ответ

3. этот совет из серии побольше гемора. во первых точно такое же регулярное выражение надо будет для правильного обхода

siv1987
На сайте с 02.04.2009
Offline
427
#3
Miracle:
ну тогда вы забыли и как минимум 4 вариант, тупо менять

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

Miracle:
2. думаю на этот вопрос я и хотел бы получить ответ

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

Miracle:
3. этот совет из серии побольше гемора. во первых точно такое же регулярное выражение надо будет для правильного обхода

Применяете то же самое регулярное выражение до тех пор пока есть совпадения по шаблону.

edogs software
На сайте с 15.12.2005
Offline
775
#4

Непонятно почему открывающий в реге у Вас spoiler а закрывающий url.

Точнее, это как раз и объясняет, почему конструкция с закрывающими spoiler не работает. Вы же закрываете не url, а spoiler.

Вообще эту задачу надо решать не регами., а простым проходом в цикле по строке.

Рекурсивные реги Вас не спасут, т.к. они больше для поиска, а не для замены. Вследствии того, что хотя Вы и можете исходное выражение для поиска составить с рекурсией - выражение для замены Вы должны написать сразу (расставив $1-$20 как положено), а поскольку количество вложенных рекурсий у Вас заранее неизвестно - выражение для замены заранее написать невозможно.

Разработка крупных и средних проектов. Можно с криптой. Разумные цены. Хорошее качество. Адекватный подход. Продаем lenovo legion в спб, дешевле магазинов, новые, запечатанные. Есть разные. skype: edogssoft
M
На сайте с 20.08.2004
Offline
376
#5

спасибо ответившим, едогс снова рад вас видеть.

урл исправил, был не прав, очипятка

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


$input = "верх
глубже
еще глубже
глубже
верх";

function parseTagsRecursive($input)
{

$regex = '#\
((?:[^[]|\[(?!/?indent])|(?R))+)\
#';

if (is_array($input)) {
$input = '<div style="margin-left: 10px">'.$input[1].'</div>';
}

return preg_replace_callback($regex, 'parseTagsRecursive', $input);
}

$output = parseTagsRecursive($input);

echo $output;

вот от сюда http://php.ru/manual/function.preg-replace-callback.html

думал тут предложат изящнее решение.

тогда прошу вашей помощи понять вот это регулярное выражение

#\
((?:[^[]|\[(?!/?indent])|(?R))+)\
#


---------- Добавлено 29.11.2015 в 22:06 ----------

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

---------- Добавлено 29.11.2015 в 22:09 ----------

siv1987:
рекурсивные выражения. разбор html и ббкодов.

может я не так ищу, но ничего не нашел.

edogs software
На сайте с 15.12.2005
Offline
775
#6
Miracle:
рекурсивное решение на самом деле есть, но, почему-то мне не нравится, уж больно запутанное

Так это рекурсивное решение на рекурсивных регулярках, а не просто рекурсивная замена регуляркой.

Еще раз - мы бы обошлись без рекурсивных регулярок. Образцы решений можно взять хоть в phpbb, хоть в vbulletin - парсинг bbкодов уже заезженная тема.

Miracle:
думал тут предложат изящнее решение.
тогда прошу вашей помощи понять вот это регулярное выражение
#\
((?:[^[]|\[(?!/?indent])|(?R))+)\
#

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

Оно вставляется, просто не отображается:)

indent в начале и конце (с квадратными скобами и слэшами) задает условие, что каждое найденное выражение должно иметь вначале открывающий тэг и в конце закрывающий.

?: просто объединяет выражения (три) в скобках в одну группу, разделенных |, само по себе ничего не делает (ставится для экономии памяти, что бы этот результат отдельно не сохранялся при разборе рега).

Первое из этих выражений соответствует "не ["

Второе соответствует "[" после которой НЕТ indent или /indent (за такое условие отвечает ?! )

Третье соответствует полной регулярке (т.е. полной, как будто $0, с indent-ами и т.д.)

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

M
На сайте с 20.08.2004
Offline
376
#7

я думаю мне проще будет задать вопросы того чего я действительно не понимаю )

за ответ выше конечно спасибо.

итак

https://regex101.com/r/oG3lT9/1

1. что я не понимаю.

почему одни скобки экранируются [ а вторые нет ]?

2. я понимаю что такое ?: как | и даже немного ?!, но я не понимаю но я все же не понимаю логики данного разбора. Начало и конец- понятно, вырезали. (?R) как бы смыл тоже понятен, хотя не поняно почему стоит именно там, но вот смысл любой символ не скобка* или [ Негативный просмотр вперёд (с отрицанием) (это зачем тут?) /? - те как открытый так и закрытый тег. spoiler] - тоже понятно.

3. делаю обратную функцию https://regex101.com/r/dS7nT0/1 что-то не работает. подскажите где лажанул?

может несколько сумбурно, но я учусь ))

спасибо

edogs software
На сайте с 15.12.2005
Offline
775
#8
Miracle:

https://regex101.com/r/oG3lT9/1
1. что я не понимаю.
почему одни скобки экранируются [ а вторые нет ]?
2. я понимаю что такое ?: как | и даже немного ?!, но я не понимаю но я все же не понимаю логики данного разбора. Начало и конец- понятно, вырезали. (?R) как бы смыл тоже понятен, хотя не поняно почему стоит именно там, но вот смысл любой символ не скобка* или [ Негативный просмотр вперёд (с отрицанием) (это зачем тут?) /? - те как открытый так и закрытый тег. spoiler] - тоже понятно.
3. делаю обратную функцию https://regex101.com/r/dS7nT0/1 что-то не работает. подскажите где лажанул?

1а) Рег-то у Вас не точно такой, как в первом Вашем посте с регом. По смыслу вроде такой же, но по записи чуть другой (из-за экранирований). Советуем ограничителями выбирать не / и \ , а все же что-то более нейтральное - типа ~ . Что бы не заниматься еще экранированием ограничителей.

1б) По поводу "почему одни экранируются, а другие нет". Экранировать необходимо только когда есть неоднозначность. Множество может начинаться с [ , поэтому это спецсимвол. Но сам по себе ] ничего не значит (только как завершающий последовательность, ЕСЛИ она вначале была начата), поэтому его можно не экранировать.

2) "Любой символ не скобка" нужен что бы выбрать все символы, которые до этой скобки, т.е. до вероятного начала тэга. ?! нужен для того, что бы выбрать скобку "[" если она не является частью нужного Вам тэга. Про /? и дальше Вы правильно поняли.

3) Просто не получится, надо сильно думать. У Вас закрывающий и открывающий тэги в "прямом" варианте отличаются только наличием / , плюс открывающий тег не содержит в себе закрывающего. В "обратном" варианте и отличий больше и открывающий тэг содержит в себе часть закрывающего. Мы бы сделали проще, просто вырезали бы "<div class=splr-h>Спойлер: показать</div>" и все - на кой он нужен при обратном преобразовании?

M
На сайте с 20.08.2004
Offline
376
#9

По поводу скобки не знал, спасибо.

По п3. Идея не плохая, и устраняет ту проблему о которой вы писали, и благодаря ей, я решил обратную проблему сначала в упрощенном варианте https://regex101.com/r/dS7nT0/5 а потом и в полном https://regex101.com/r/dS7nT0/6. А проблема то была в <(?!div>, хотя если честно то я просто ошибся, но оно работает, правда логика теперь стала не понятна. Ведь должно искать закрывающийся тег... Но ведь работает. ) ,по крайней мере на сайте!

---------- Добавлено 30.11.2015 в 08:42 ----------

edogs:
В "обратном" варианте и отличий больше и открывающий тэг содержит в себе часть закрывающего.

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

---------- Добавлено 30.11.2015 в 10:25 ----------

к сожалению с preg_replace_callback не работает... странно конечно.

edogs software
На сайте с 15.12.2005
Offline
775
#10
Miracle:
Подумал если рассматривать открывающися эл-т как цельную единицу, то не вижу проблемы описанной вами, но, может и ошибаюсь.! ))

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

Miracle:
к сожалению с preg_replace_callback не работает... странно конечно.

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

12

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий