Миру - мир. А Вам - пломбир!
Доброго времени суток, сообщники!

Хотите немного ненормального программирования? :3 Нет, я не буду пытаться парсить html. Всё чуточку проще.

tl;dr: смотреть сюда, там понятны как регексп, так и задание плюс автоматически можно играться/проверять.

Подробнее.
Дано
Некоторый текст, в котором находится номер телефона в различных вариантах. Список:


Надо
Регекспами (PCRE) сматчить номер, но только в том случае, если он не московский и только если он не обёрнут в тег с определённым классом "foobar":


Упрощаем жизнь
Перед номером может быть всего два кода (812 или 495) или никакого вообще (пустой
считать питерским).
Обёртка находится всегда вплотную (достаточно искать строку класса в теге перед номером).


Усложняем бытие
Код города (и только он) может быть обёрнут в пустой span и/или быть в скобках.


В чём проблема?
Отрицание для группы (?!495) работает странно даже в паттернах типа /((?!495).*)/gui – не матчит четвёрку, но строку с ней считает найденной. Отсюда два вопроса:
1. Как сделать так, чтобы регексп вообще пропустил всю строку, где есть 495?
2. Почему регексп отрицает только первую цифру 4, а не все остальные?
3. Общие пожелания для улучшения регекспа тоже принимаются.

Сам регексп можно посмотреть и автоматически затестить вот здесь.

Спасибо и have fun!

@настроение: o.0

@темы: *nix, regex, Computer Science, PHP, pcre

Комментарии
18.07.2014 в 02:55

тролль - это не только ценный жир, но и 3-4 легкоусвояемых коммента ежедневно
насчёт "не пытайтесь парсить html" не соглашусь
с помощью рекурсивных регэспов - очень даже можно!
кстати, никогда не понимал, почему многим так нравится тот пост на SO

по сути задачи - я бы сначала разбил текст на отдельные телефоны
есть ли в php фича "вызвать callback-функцию для каждого найденного совпадения с регэкспом"?
18.07.2014 в 03:13

Миру - мир. А Вам - пломбир!
> рекурсивных регэспов
От такого даже блог ушёл в прострацию:"Unhandled Exception. An unhandled exception was thrown by the application.". Согласен с тем, что регекспами можно парсить html, но только в узких (и часто одноразовых) задачах.

> есть ли в php фича "вызвать callback-функцию для каждого найденного совпадения с регэкспом"?
В целом да. Выглядят как-то так:

Для замен коллбэки ближе к нормальным:


Я пока вот чего не могу понять – в примерах на SO и прочих регексп при отрицании не матчит всю строку. А у меня оно всего-лишь не включает отрицание в результат.. да и то как-то частично ):
18.07.2014 в 03:25

тролль - это не только ценный жир, но и 3-4 легкоусвояемых коммента ежедневно
@дайрик и тут гадит - он, как оказывается, автоматически заменяет латинскую букву на визуально похожую русскую (!!!) в адресах размещённых на дайриках ссылок не только для слова javasсript, но и для слова expressions
@криворукие @админы, бля
короче, через гугл статья легко ищется
18.07.2014 в 04:02

Миру - мир. А Вам - пломбир!
Странная группа "??" (о.0) Пых такого не умеет. Онлайн-приложуха сожрала все ядра i5 и надолго (предполагаю, что навсегда) так что, считай, js даже если и умеет, то не может.
А вообще, это интересная тема, спасибо! Может, получится с ними рекурсивно не-матчить.

> я бы сначала разбил текст на отдельные телефоны
Чтобы разбить текст на телефоны, сначала нужно их из текста выцепить, а чтобы выцепить – сматчить регекспом (: Пони бегает по кругу.