Миру - мир. А Вам - пломбир!
Доброго времени суток, сообщники!
Хотите немного ненормального программирования? :3 Нет, я не буду пытаться парсить html. Всё чуточку проще.
tl;dr: смотреть сюда, там понятны как регексп, так и задание плюс автоматически можно играться/проверять.
Подробнее.
Дано
Некоторый текст, в котором находится номер телефона в различных вариантах. Список:
Надо
Регекспами (PCRE) сматчить номер, но только в том случае, если он не московский и только если он не обёрнут в тег с определённым классом "foobar":
Упрощаем жизнь
Перед номером может быть всего два кода (812 или 495) или никакого вообще (пустой
считать питерским).
Обёртка находится всегда вплотную (достаточно искать строку класса в теге перед номером).
Усложняем бытие
Код города (и только он) может быть обёрнут в пустой span и/или быть в скобках.
В чём проблема?
Отрицание для группы (?!495) работает странно даже в паттернах типа /((?!495).*)/gui – не матчит четвёрку, но строку с ней считает найденной. Отсюда два вопроса:
1. Как сделать так, чтобы регексп вообще пропустил всю строку, где есть 495?
2. Почему регексп отрицает только первую цифру 4, а не все остальные?
3. Общие пожелания для улучшения регекспа тоже принимаются.
Сам регексп можно посмотреть и автоматически затестить вот здесь.
Спасибо и have fun!
Хотите немного ненормального программирования? :3 Нет, я не буду пытаться парсить html. Всё чуточку проще.
tl;dr: смотреть сюда, там понятны как регексп, так и задание плюс автоматически можно играться/проверять.
Подробнее.
Дано
Некоторый текст, в котором находится номер телефона в различных вариантах. Список:
Надо
Регекспами (PCRE) сматчить номер, но только в том случае, если он не московский и только если он не обёрнут в тег с определённым классом "foobar":
Упрощаем жизнь
Перед номером может быть всего два кода (812 или 495) или никакого вообще (пустой
считать питерским).
Обёртка находится всегда вплотную (достаточно искать строку класса в теге перед номером).
Усложняем бытие
Код города (и только он) может быть обёрнут в пустой span и/или быть в скобках.
В чём проблема?
Отрицание для группы (?!495) работает странно даже в паттернах типа /((?!495).*)/gui – не матчит четвёрку, но строку с ней считает найденной. Отсюда два вопроса:
1. Как сделать так, чтобы регексп вообще пропустил всю строку, где есть 495?
2. Почему регексп отрицает только первую цифру 4, а не все остальные?
3. Общие пожелания для улучшения регекспа тоже принимаются.
Сам регексп можно посмотреть и автоматически затестить вот здесь.
Спасибо и have fun!
с помощью рекурсивных регэспов - очень даже можно!
кстати, никогда не понимал, почему многим так нравится тот пост на SO
по сути задачи - я бы сначала разбил текст на отдельные телефоны
есть ли в php фича "вызвать callback-функцию для каждого найденного совпадения с регэкспом"?
От такого даже блог ушёл в прострацию:"Unhandled Exception. An unhandled exception was thrown by the application.". Согласен с тем, что регекспами можно парсить html, но только в узких (и часто одноразовых) задачах.
> есть ли в php фича "вызвать callback-функцию для каждого найденного совпадения с регэкспом"?
В целом да. Выглядят как-то так:
Для замен коллбэки ближе к нормальным:
Я пока вот чего не могу понять – в примерах на SO и прочих регексп при отрицании не матчит всю строку. А у меня оно всего-лишь не включает отрицание в результат.. да и то как-то частично ):
@криворукие @админы, бля
короче, через гугл статья легко ищется
А вообще, это интересная тема, спасибо! Может, получится с ними рекурсивно не-матчить.
> я бы сначала разбил текст на отдельные телефоны
Чтобы разбить текст на телефоны, сначала нужно их из текста выцепить, а чтобы выцепить – сматчить регекспом (: Пони бегает по кругу.