Вступление

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

Для начала, поговорим о том, что такое регулярные выражения, и каково их практическое применение.

Регулярные выражения — что это?


Процитирую Википедию:
Регулярные выражения — система синтаксического разбора текстовых фрагментов по формализованному шаблону, основанная на системе записи образцов для поиска.

Если говорить проще, регулярные выражения — некие шаблоны, по которым можно проводить проверку, изменение или поиск чего-либо в любых текстовых данных. Например, можно проверить валидность email, заменить некоторые слова на другие (допустим для орфографирования текста), парсить довольно сложный контент, и т. п.

Регулярные выражения на практике


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

Довольно часто мне приходится работать с текстом, в частности с валидацией и парсингом. Ранее приходилось использовать стандартные функции языка для работы с текстом, самому писать логику. Сейчас, после того, как я вник в регэкспы, вся работа сократилась до написания пары строк.

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

P. S. ППНХ.
P. P. S. Если интересно, кидайте задачи по работе с текстом, возможно будут топики с описанием их решения.
_________
Текст подготовлен в ХабраРедакторе
+63
28 марта 2009, 15:14
54

комментарии (61)

+10
eyeofhell #
Конечно интересно, жду продолжения. Понятное дело интересует общая концепция — «место точки в регэкспе», «почему у всех систем разный синтаксис», «типовые шаблоны поиска и как они решаются регекспами», «многострочность и перевод стоки — что о них известно регекспам и как с этим бороться», «подставновка и замена — что регэкспы могут а что нет»
0
KeepYourMind #
Спасибо за варианты топиков. Но такие объемы и моя занятость не очень совместимы. Так что если найдется тот, кто может помочь — велкам.
0
eyeofhell #
А Вы понемножку :). Вот про могострочность в реекспе — очень мало информации в сети. И про то какой вариант регекспов в каких системах используется.
+4
KeepYourMind #
Буду стараться на благо Хабранации.
0
Goodkat #
gskinner.com/RegExr/ вот < — неплохой браузерный валидатор регэксов
0
WGH #
Мне файрбага хватает :)
0
Goodkat #
не знал, что он умеет
и где именно он умеет регэксы? или просто javascript?
0
WGH #
да, джаваскрипт
но ваша ссылка в любом случае полезна
+1
bappoy #
почитайте 6 главу «Perl Cookbook», там эти вопросы очень подробно рассматриваются, и большая часть оттуда применима к регэкспам в sed/vim/grep/awk и вообще везде.
+2
bioroot #
В принципе дело полезное. Не знаю, правда, стоило ли под него отдельный блог заводить. Общая теория будет полезна, хотя мне бы было интересно почитать о частностях реализации. А то бывало увидишь что язык поддерживает PCRE, обрадуешься, а потом в сложных выражениях такие «частности» вылезают, что выть хочется.

На счёт помочь — могу набросать вводную статейку по пыхе, хотя не знаю насколько это будет актуально.
0
l2k #
Ну значит ждите первую статейку :)))) для начавших… Давно думал, в какой блог засунуть!
+3
sylvio #
«ппнх» — ужасно звучит и это, кстати, ваш второй пост.

А по регекспам у меня есть три простых вопроса:
1. Как работать с группой символов?
Например у меня есть много строк вида «паша молодец\n саша умница\n витя дурак\n сева отличник» и нужно заматчить все, где нету слова «дурак». Что-то вроде /^(.*?) (^дурак)$/.

2. Возможно-ли указать количество вхождений символа?
Например у меня есть много странных слов вроде «пампарам\n парампампам\n пампампам\n тудумс\n парарам». И нужно получить все слова состящие из букв «памр», но где «р» встречается только 1 раз. Что-то вроде /[памр{1}]*?/.

3. Есть ли под-регекспы?
Или даже рекурсивные, не знаю как точно назвать.
Например я имею много структур вида «Человеки { Умные [Андрей, Сергей] Глупые [Юра, Лена] Никакие [Стив, Билл] }». И не хочу в начале искать все структуры вида /[^{\s]*? {[^{]*?}/, затем все /[^\[\s]*? \[[^\[]*?\]/, а уже затем /(.*?),?/. В общем, все это запихнуть в один регексп.
+1
leonidas #
1) правильнее искать не попадающие под ваше выражение unless m/дурак$/

2) будет что то вроде m/^(?:(?! рр)[памр])+$/

3) если я правильно понял, то чего вы хотите, задача решается без рекурсий, а простым вложением сгруппировав выражения, если говорить о рекурсиях, то они есть (можно создать переменную, после в неё написать регулярку и из неё же сослаться на себя)
+2
bioroot #
Гы. Ну давайте сразу с места в карьер. )

1. '/^([^\r\n]*?)(?<! дурак)$/m'
Начнём с модификатора. m (PCRE_MULTILINE) позволяет утверждениям начала (^) и конца ($) ловить не только начало / конец выражения, но и начало / конец строки. Т.е. в нашем случае \n.

Выражение [^\r\n]*? позволяет поймать все символы, за исключением перевода строки (иначе бы например «витя дурак\nсева отличник» попало бы под критерий, т.к. далее мы требуем лишь отсутствия слова «дурак» в конце выражения). (?<! дурак) — это отрицающее заглядывание. Оно проверяет, нет ли в конце строки уже содержащейся в ([^\r\n]*?) на конце слова «дурак». Если есть — выражение провалится и перейдёт к следующей строке (на самом деле оно провалится, когда попытается откатится к предыдущему выражению и сожрать ещё один символ, которым в нашем случае является конец строки ($ = "\n"), но это уже тонкости, хотя и важные).

Соответственно для поиска всех «дураков» нужно изменить «знак» заглядывания. Т.е. вместо (?<! дурак) написать (?<=дурак).

2. '/^([^р\W]*? пара[^р\W]*?)$/m' — если я вас правильно понял.
Это выражение позволит найти все слова, в которых встречается сочитание «пара» и в других частях отсутствуют буквы «р». Уже знакомые ^ и $ обозначают те же начало и конец строки в многострочном режиме (с модификатором m). Две одинаковые части [^р\W]*? описывают то, что мы будем считать символом слова. По сути ловят всё, кроме буквы «р» и так называемой границы слова \W. Границей слова считается любой не буквенно-цифренный символ, исключая "_". Т.е. тут написано «ищи всё, что является символами слова за исключением буквы 'р'». Модификатор *?, о котором я забыл упомянуть выше, подавляет «жадность». Жадность — это свойство регулярного выражения искать как можно больше символов, входящих в него. Подавление позволяет искать минимальное вхождение. Иначе бы выражение [^р\W]* ловило все символы, пока не упералось бы в границу слова или букву «р». В принципе в нашем примере это не критично, т.к. перенос строки "\n" подойдёт под критерий \W, но я решил его оставить по соображениям логичности.

В сухом остатке имеем выражение: ищи от начала строки любое количество (в том числе и 0, т.к. * обозначает от нуля до бесконечности) символов слова, исключая «р», затем фрагмент «пара», затем ещё раз символы слова исключая «р», затем конец строки.

3. Есть. Но не надо. ) А задачу я так и не понял.

Главный совет — не заморачивайтесь на регах. Обычно они работают очень медленно. И чаще всего их можно заменить небольшим куском эквивалентного кода, который гораздо быстрее. Половина искуства обращения с регами состаит в том, чтобы использовать их как можно реже. Ну или когда скорость — дело десятое.

P.S.: Это для пыхи. Одни из самых подлях граблей в PCRE на разных языках как раз в «заглядываниях». Но это в основном относится к альтернативам разной длинны, так что скорее всего и в других языках покатит, где заглядывания вообще есть.
+2
thestorm #
Спасибо за инициативу, но почему? почему все пишут одинаково «Был весьма удивлен что нет такого блога». Ну раз не было, значит надо было создать. Вы почти год на хабре и не говорите что вы сильно удивлены, как-то пафосно звучит

жду хороших статей
0
Spryt #
слабоватенько, ожидал большой мануал, ну или хотя бы руководство к действию… Сам с трудом научился воспринимать регеэкспы, вот только сегодня полчаса мучился, пока не понял, что (.*) в рнр по умолчанию не включает перевод строк, и надо указать флаг /s…

для примерчиков советую посмотреть в pcre.ru, я оттуда первые парсеры делал (выборка всех ссылок из кода и т.д.) :)
+1
AlienZzzz #
1. Вот очень удобная штука всегда пользуюсь ей:
_http://gskinner.com/RegExr/
2. Вот еще www.regular-expressions.info/
______________________

+1
mironov_anton #
Вот еще очень удобная штука: www.rubular.com
0
tiesto #
Очень интересно было бы узнать все особенности регекспов в sed и awk.
+8
s_a_p #
Определение регулярных выражений из Википедии и анонс разбора регекспа для мыла набирает 16 плюсов. Я хренею, что за детский сад?

P.S. /^(\S+)@([a-z0-9-]+)(\.)([a-z]{2,4})(\.?)([a-z]{0,4})+$/i следующую «статью» можете не писать.
0
chiaroscuro #
Школьники в действии.
–4
GrustniyKot #
Как ни удивительно — не все знают про википедию.
+2
KeepYourMind #
И кто поймет что вы тут написали, и как это работает без навыков работы с регэкспами? Я планирую статьи в основном для новичков.
–2
sylvio #
По тому что сами не очень их понимаете или по тому, что считаете, что на минимальном уровне их сложно освоить?
+2
KeepYourMind #
Потому что они на самом деле сложны для новичков. Особенно оптимизация. Можно написать работающее выражение, но оно будет жрать все ресурсы.
+6
roh_roh #
user@subdomain.domain.com невалидный, а &^$%!#&@domain.com валидный выходит. не гут :)

а в остальном нельзя не согласиться
+1
arto #
у вас неверное выражение
+2
darkk #
Вы [a-z], который не чтит RFC. Посылаю вам луч ненависти.
Да, кстати, под ваш регэксп не попадает, например, username@orgchem.univer.omsk.ru — вполне реальный домен.
+6
Bonch #
Ну и неправильный регэксп. Не все емэйлы он отловит, хотя бы уже из-за этого: ([a-z]{0,4}. Есть, например, зона .museum
(\S+) — 1 или более непробельных символов. Угу, значит, я могу и $%#bla@mail.ru написать, и оно проканает.

12 плюсов за неправильный регэксп, что за детский сад?
0
Nikita #
Ну и email типа bobuk@radio-t.com тоже не пройдёт =)

Ну это не важно.

А от автора хотелось бы услышать, описания и интересные примеры использования RegExp с пред и пост условиями.
+2
GrustniyKot #
Спасибо что начали этот блог. Даже если вы не будете писать часто на эту тему, найдутся другие авторы которые в него напишут. Если найду время и силы, постараюсь тоже написать несколько статей здесь.

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

А сухие краткие инструкции по применению — не всегда понятны.

Так что Велкам!
+1
chiaroscuro #
> Регулярные выражения — что это?

Это определение множества строк.

> Регулярные выражения на практике

Практически не встречаются. (ибо regex совсем не regular expression)

> Довольно часто мне приходится работать с текстом, в частности с валидацией и парсингом. Ранее приходилось использовать стандартные функции языка для работы с текстом, самому писать логику. Сейчас, после того, как я вник в регэкспы, вся работа сократилась до написания пары строк.

Ну а завтра я открою для себя описание грамматики посредством BNF, и будет вообще зашибись.

/blog
+18
ykcyc #
У xkcd был комикс очень в тему нового блога:

оригинал:
xkcd.com/208
–3
join #
для чего целый блог? )

если не знаете рег выражения RegExBuddy вам в помощь )
+2
begezavr #
Ну заколебали, чесс слово. Ну ненужен тебе этот блог — ну пройди мимо, ну поставь минус если считаешь, что он и другим не нужен (смешно, да).
+2
roh_roh #
а мыло проверяется вот таким вот регекспом: www.ex-parrot.com/~pdw/Mail-RFC822-Address.html
0
darkk #
Да-да-да! А половина %#$*ых сайтов даже «+» в username не дают вставить.
–3
Gangsta #
С удовольствием буду читать топик и помогать ньюбам. Сам в свое время открыл для себя регулярные выражения, а сейчас уже стал гуру со стажем. Блог нужный!
+1
Zabatov #
Это вы сами себя гуру со стажем назвали? )
–3
Gangsta #
Зрение вас не подвело
–2
Gangsta #
Мде, после наставленных минусов желание кому-то помогать пропало.
–1
nikitad #
Лучший способ изучить регулярные выражения — написать свою реализацию.
0
Goodkat #
наверное, гуру так и сделали, и теперь мы имеем несколько слабосовместимых между собой реализаций регулярных выражений :)
0
nikitad #
Принципиально они работают одинаково, существование нескольких стандартов — другой вопрос. Можно выбрать ту, что нравится и реализовать ее.
0
Xronos #
Теория конечных автоматов, графы как раз с них надо начинать а не с валидацией url и email =). Но это сухая теория так что продолжим с валидацией урлов…
0
onix74 #
Когда ждать продолжения?
0
KeepYourMind #
Завтра.
+1
Deepwalker #
Посмею себе дать направление всем интересующимся на величайший труд по теме многоуважаемого Фридла — Регулярные выражения. Дж. Фридл., www.softtime.ru/info/fridl.php Ну а лучше конечно приобрести сей труд.
0
mironov_anton #
А ни у кого под рукой нету регекспа для валидации jabber id?
0
darkk #
Правильного, думаю, нет. В username-части можно использовать юникод, а это вызывает некоторые проблемы.
0
Xp0M0u #
Для составления и проверки выражений, часто использую http://myregexp.com/
+2
Kalan #
В следующем топике я планирую рассмотреть валидацию email, как самый популярный пример использования.


В соответствии с RFC получается вот так:

(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*:(?:(?:\r\n)?[ \t])*(?:(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*)(?:,\s*(?:(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*|(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)*\<(?:(?:\r\n)?[ \t])*(?:@(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*(?:,@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*)*:(?:(?:\r\n)?[ \t])*)?(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|"(?:[^\"\r\\]|\\.|(?:(?:\r\n)?[ \t]))*"(?:(?:\r\n)?[ \t])*))*@(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*)(?:\.(?:(?:\r\n)?[ \t])*(?:[^()<>@,;:\\".\[\] \000-\031]+(?:(?:(?:\r\n)?[ \t])+|\Z|(?=[\["()<>@,;:\\".\[\]]))|\[([^\[\]\r\\]|\\.)*\](?:(?:\r\n)?[ \t])*))*\>(?:(?:\r\n)?[ \t])*))*)?;\s*)

(источник)
0
KeepYourMind #
Хммм…

Попробывал пропустить это выражение через The Regex Coach. Оказывается такие email валидны:
------------@-----.---
!#$%^&*@!#$%^&*.ru
fuck @ my. mozg (именно с пробелами)

Кто нибудь объяснит, почему? Может по RFC это верно, но у меня есть сомнения.
0
Nikita #
там вокруг этого regExp есть ещё какая-то проверка, возможно она эти типы отловит.

«This regular expression will only validate addresses that have had any comments stripped and replaced with whitespace (this is done by the module).»
+2
KeepYourMind #
Получается, что этот модуль сначала готовит мыло к проверке, только потом проверяет этим регэкспом?

У меня нет желания вникать в этот регэксп, но мне он не нравится.
0
Nikita #
Не смогу не согласиться. Регэксп отвратительный.

Не представляю, как его отладить. Правда, есть предположение, что он создан какой-то «регэкспо-генерацией», на основе, например, грамматики.
+1
Xobb #
Моя умеет регэкспы читать, но не умеет писать.
0
homm #
> P. S. ППНХ.
Что это значит то? На всякий случай: сам ПНХ.
0
Londeren #
ППНХ — Первый Пост На Хабре ;)
0
homm #
Интересно. зачем было писать непонятные буквы, да еще и так похожие на известную всем аббревиатуру.
+1
Mordraug #
…несколько эзотеричными…


во-во… шаманство это всё =)

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