Регулярные выражения perl

IG_rok777

Добрый вечер, уважаемые гуру. Мучает меня проблема.
Есть регулярное выражение, которое отыскивает первое вхождение [IF ...]|[ELSE]|[ENDIF] и запоминает окружающий их текст.
Никак не могу заставить его работать. Помогите, пожалуйста :)
Составил максимум вот это: /^([^(IF|ELSE|ENDIF)]*)\[(IF|ELSE|ENDIF\s)*([^\]\[]*)\](.*)$/s
Этот шаблон не хочет искать, когда перед IF, ELSE или ENDIF встречается, например, точка. Не знаю как остальные символы (буквы, скобки, двоеточие все катит но это как признак того, что шаблон составлен не правильно.
Чую, что нужно использовать конструкцию (?<! шаблон но не знаю как.
Или может использовать ленивый алгоритм поиска и не заморачиваться с проверкой не вхождения (IF, ELSE, ENDIF) вначале, но опять же, не знаю как.

tokuchu

[^(IF|ELSE|ENDIF)]
А это что за конструкция? В [] вроде символы только указываются, а не слова.

IG_rok777

В том-то и дело, это результат моего творческого подхода.

doublemother

Что подразумевается под окружающим текстом?
^(.*?IF|ELSE|ENDIF?:.(?!IF|ELSE|ENDIF+)

выберет кусок текста от начала строки до первого IF/..., само ключевое слово, и всё последующее до очередного ключевого слова.

IG_rok777

выберет кусок текста от начала строки до первого IF/..., само ключевое слово, и всё последующее до очередного ключевого слова.
Спасибо, неплохая идея, а как быть, если следующего нет?

doublemother

Тогда просто дойдёт до конца

val63

Если я правильно понял, чо те надо, попробуй чонить типа такого:
^.*?\bIF\b.*?\bELSE\b.*?\bENDIF\b.*$

IG_rok777

/^(.*?)\[(IF|ELSE|ENDIF\s*[^\]]*)\]?:.(?!\[IF|\[ELSE|\[ENDIF+.*)$/s

Вот такой окончательный вид приняло выражение. Все спасибо. Отдельно большое спасибо =)

val63


(\s*[^\]]*)
Можешь сократить до [^\]]*
Кстати, у тебя поймается например такое:
[IFhello I'm Muzzy] I like clocks  

Barbie29

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

val63

Это такой вид троллинга - показать неработающую регулярку :-)

IG_rok777

Кусок текста для парсинга:
<tr>
<td><p>
[IF field="Администрация"]
[Дата format="date:DD.MM.YY"]<br>
<b>Администрация:</b> <i>[Отзыв]</i><br>
[ELSE]
[Дата format="date:DD.MM.YY"]<br>
<b>ФИО:</b> [ФИО]<br>
<b>Оценка:</b> [Оценка]<br>
<b>Род занятий:</b> [РодЗанятий]<br>
<b>Возраст:</b> [Возраст]<br>
<b>Отзыв:</b> [Отзыв]<br>
[ENDIF]
<table style="margin-left: 30px;">
[children order="Дата"]
</table>
</td>
</tr>

В общем случае должна быть вложенность конструкции IF ELSE ENDIF.
1. Сначала нужно получить самую первую, если нет, то заканчиваем.
2. Проверить условие и оставить в тексте подходящий блок. Шаг 1.

val63

А вложенные ифы у тя бывают?

IG_rok777

У меня пока еще не было. Но, думаю, необходимость возникнет.

val63

FYI: вложенные конструкции не ловятся чистыми регулярками, пиши нормальный парсер сразу лучше

IG_rok777

Ну так для этого я и лювлю первое вхождение. Есть счетчик блоков if и el. когда if = 1 el = 1, значит дошли до else от первого if. if = 0 el = 0 значит конец блока else.

Dasar

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

IG_rok777

Спасибо, интересная штуковина. В перспективе очень пригодится.

ermsoft

В perl 5.10 можно использовать рекурсию в регэкспах, и соответственно матчить вложенные выражения: Can I use Perl regular expressions to match balanced text? .
Но если грамматика более-менее сложная, лучше и правда использовать что-нибудь другое.
Вот, например, есть Marpa. Это не peg, это универсальный bnf-парсер.
Оставить комментарий
Имя или ник:
Комментарий: