/^(?:[0-9]|[a-z]|[\._%\+-])+(?:@)(?:[0-9]|[a-z]|[\.-])+(?:\.)[a-z]{2,}$/i
С новым вкусом SLR:
На пост заметка не тянет, но на новость вполне. Дабы не тянуть кота за хвост, я вынес суть выше хабраката. Теперь потяну. В духе Хабра-Твиттера, прошу любить и жаловать: simple-regex.com — создание регулярок простым языком.
Для начала, это не я придумал, к сожалению. Сайт на английском, статьи как таковой нет, поэтому я не могу представить вам перевод. Сегодня я заглянул в привычный PHP подреддит, и увидел там тему «I've built a SQL-like language that compiles to regular expressions — What do you think?», по-русски «Я создал SQL-подобный язык, который компилируется в регулярные выражения». Вот так, ни больше ни меньше. Как написано в одном комментарии «Поздравляю! Ты только что сделал одно из моих самых мистических умений устаревшим!» Поэтому спешу поделиться с Хабра-сообществом, дабы все были в курсе.
Да, это близкий к естественному языку способ создания регулярок. На сайте можно найти несколько примеров. Тот, что я привёл вверху — проверяет почтовые адреса.
А вот этот:
begin with capture (letter once or more) as "protocol",
literally "://",
capture (
letter once or more,
any of (letter, literally ".") once or more,
letter at least 2 times
) as "domain",
(literally ":", capture (digit once or more) as "port") optional,
capture (literally "/", anything never or more) as "path" until (any of (literally "?", must end)),
literally "?" optional,
capture (anything never or more) as "parameters" optional,
must end,
case insensitive
Служит для проверки URL, и компилируется в такую регулярочку, что Хабр даже не позволяет её правильно отобразить, поэтому я не могу её вставить, простите. Но в разделе примеров ещё много примеров. И на сайте они цветные, там читать удобнее, так что посетите, не пожалеете.
Чего на сайте я не нашёл, но что очень просится, так это реализация цепочки вызовов для задания условий. Но это есть в репозитории!
$query = SRL::startsWith()
->anyOf(function (Builder $query) {
$query->digit()
->letter()
->oneOf('._%+-');
})->onceOrMore()
->literally('@')
->anyOf(function (Builder $query) {
$query->digit()
->letter()
->oneOf('.-');
})->onceOrMore()
->literally('.')
->letter()->atLeast(2)
->mustEnd()->caseInsensitive();
Насколько это полезно покажет время. Но для начинающих программировать это явно очень упрощает тему знакомства с регулярками.
Я честно говоря, не знаю, кто автор этой штуки, но она выглядит весьма интересно. Тема на реддите размещена юзером AndroTux. Вот ссылка на репозиторий на ГитХабе. Тут можно видеть, что единственный контрибутор проекта — Karim Geiger, который разместил этот проект в репозитории компании tyvr.net, которая указана у него же в профиле. Видимо, это его же студия программистов, которые программируют за деньги. Желаю им удачи!
Комментарии (71)
franzose
31.08.2016 09:23-5Сначала подумал, было, написать про «Владимирский астрал, эзотерика», но потом решил, что не буду.
wolfandman
31.08.2016 09:29+10А почему нет? Мне нравится идея. Не думаю, что сам бы использовал, т.к. к регуляркам привык, но для новичков — вполне бы сгодилось.
EvilsInterrupt
31.08.2016 11:52+1Ну видя код, который не работает и видя в нем регулярку. Насколько вы застреваете чтобы убедиться, что регулярка корректна?
bromzh
31.08.2016 10:17+3Сайт не отвечает, видимо его постиг хабраэффект.
Для разъяснения и тестирования регекспов есть, например, отличный ресурс: https://regex101.com/
А вводить новый непонятный синтаксис регекспов — не слишком хорошая идея.
Sirion
31.08.2016 10:32+8Главная проблема регекспов в том, что они write-only. Описанный в статье подход эту проблему решает. Хотя любители однострочников на перле негодуют, да.
Не знаю, буду ли использовать, но запомню, что существует.impwx
31.08.2016 10:37+9Проблема трудночитаемости регулярок решается так же, как проблема трудночитаемости обычного кода — выравниванием и комментариями. Во многих языках поддерживается, но, к сожалению — не во всех.
Fedcomp
31.08.2016 11:00-4Проблема чтения машинных кодов решается в выравнивании кода и расставлении комментариев. Но мы же не используем машинные коды правда?
impwx
31.08.2016 11:24+12Синтаксис регулярных выражений — это уже мнемоническая надстройка над внутренним представлением, как ассемблер над машинными кодами. Предлагаемый в статье вариант не создает новый уровень абстракции, а просто заменяет одну строку на другую, более длинную — как если бы вместо
mov ax, 0
пришлось писатьset first register to value zero.
asoukhoruchko
31.08.2016 13:38-2Разница в том, что эту строку вполне сможет понять человек без предварительной подготовки (по крайней мере, после пары примеров).
А регулярки читаются не сильно хорошо.impwx
31.08.2016 14:08+5Сложность понимания синтаксиса регулярок, имхо, преувеличена. На первый взгляд они выглядят пугающе, но по факту возможные элементы можно пересчитать по пальцам — группы, квантификаторы, альтернативы, штук пять спецсимволов и всякие редкие вещи типа опережающих проверок. Всё это можно запомнить за вечер, а с подсветкой синтаксиса становится еще проще. Так что всё упирается в сложность самого выражение — проверку email-адреса по RFC одинаково невозможно постичь в любой форме записи.
Остается вопрос того, стоит ли доверять человеку без подготовки править код, руководствуясь наивным пониманием синтаксиса. Зачастую это чревато возникновением сложноуловимых багов — например, неопытный программист на C или JS может написатьif(a = true)
и долго удивляться, почему сравнение не работает, как надо.
nitso
31.08.2016 10:58+6Пример в начале статьи совсем плох.
Во-первых он уменьшается примерно раза в два, ликвидировав неиспользуемые группировки и объединив перечисления. Во-вторых, экранирование в перечислениях не нужно. И получается вполне читабельно:
^[0-9a-z._%+-]+@[0-9a-z.-]+\.[a-z]{2,}$
И, наконец, Прекратите проверять Email с помощью регулярных выражений!
После небольшой тренировки небольшие однострочные регулярки воспринимаются достаточно быстро. А вот словесный многострочный аналог требует больше времени для чтения.
Сложные выражения в SLR займут экран, воспринимать будет даже сложнее, чем открытый в отладчике (упомянутый выше regex101, например) оригинал.
А есть специальные сервисы для визуализации regexigordata
31.08.2016 11:16-5Проверка имейла регуляркой по большому счёту может быть сведена до /.+@.+/, но это же просто пример. Можете написать автору и предложить свой пример, заодно потестируете новую тулзу.
punkkk
02.09.2016 13:19+2Вы немного не уловили… Сократить регулярку != урезать. nitso сократил, а вы урезали. Хотя проверять email регулярными выражениями достаточно непрактично.
igordata
03.09.2016 11:29+3Учитывая существование национальных доменов, я не могу сказать что проверка мыла на латинский алфавит имеет хоть малейший смысл…
vintage
31.08.2016 11:31+9Лучше всё же, использовать грамматики, а не "очеловечивать" регулярки. Например, для вашего парсера урлов можно запилить такую грамматику на
grammar.tree
:
URL is PROTOCOL string =:// DOMAIN optional string =: PORT PATH optional QUERY PROTOCOL is list-of LETTER DOMAIN is list-of list-of LETTER string =. LETTER list-of LETTER PORT list-of DIGIT PATH is string =/ optional list-of symbol except =? QUERY is string =? optional list-of symbol except =# LETTER is symbol =abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ DIGIT is symbol =0123456789
s-kozlov
01.09.2016 07:48О боже, в Вашем «убийце YAML» всё еще используется " =".
vintage
01.09.2016 10:12А какой символ порекомендуете для маркера начала сырых данных?
s-kozlov
01.09.2016 11:44Вам уже в комментах к той статье говорили, что "=" и " = " читабельнее " =".
vintage
01.09.2016 12:13И я не раз повторял, что "=" — не разделитель "ключа" и "значения". Я согласен, что символ равенства вводит в заблуждение и было бы правильнее использовать какой-либо другой символ, например "|", но он в разных раскладках набирается разными способами, что несколько фрустирует.
vintage
01.09.2016 12:20Хотя, я тут подумал, из символов, набираемых одинаково в любой раскладке ("-", "_", "=", "+", "\") лучше подойдёт символ обратной косой черты. Он достаточно редкий в обычных данныхи используется в основном для похожей задачи — экранирования символов.
Miraage
31.08.2016 12:01+2Чего люди не придумают, лишь бы не учить регулярные выражения.
А учить там — с гулькин нос, по факту.VladC
31.08.2016 12:20+2Никогда не пытался их учить, они слишком редко пригождаются, чтобы ими голову забивать, достаточно держать под рукой шпаргалку.
saluev
31.08.2016 20:04Шпаргалка — это понятно. Вопрос в том, насколько хорошо вы представляете, какие задачи решаются регулярными выражениями, а какие — нет.
asoukhoruchko
31.08.2016 13:50По факту получили Builder для регулярок, что неплохо (и даже можно подумать про портировать на другие языки).
Отдельный язык для такой задачи кмк перебор. Т.е. пока не ясно, как это использовать для самостоятельных задач.
ifgem
31.08.2016 14:01+2У Rebol/Red есть невероятно удобный и читабельный PEG диалект(parse).
Первый пример из статьи.
test: "superb@ya.ru" digit: charset [#"0" - #"9"] ; еще один диалект. letter: charset [#"a" - #"z" #"A" - #"Z"] symbol: charset "._%+-" rule: [ some [digit | letter | symbol] "@" 2 [letter | "."] any [letter | "."] ] parse test rule
pengyou
31.08.2016 14:30-2Уважения заслуживают такие люди, как автор этого языка, которые делают Своё.
akastargazer
31.08.2016 15:14+2Зачем делать Своё, когда есть серьёзные и, главное, надёжные корпорации, которые сделают Своё лучше и быстрее? Если уже не сделали. Они же нам выдадут это бесплатно, в рамках рыночного планетарного прогрессорства.
vintage
31.08.2016 16:46Затем, чтобы эти серьёзные и (главное!) надежные корпорации, взяли тебя на работу и ты делал Своё лучше и быстрее. :-D
stychos
31.08.2016 14:59+1Отрадно увидеть что-то действительно новое, пусть сообщество и плюётся кое-где.
punkkk
31.08.2016 15:29+4Непонятен профит, это как обратный alias по сути, не очень комфортно. Регулярные выражения познаются не так сложно и не менее трудно читаются, дело легкой привычки.
Одно begin with, вместо циркумфлекса уже настораживает.saluev
31.08.2016 20:07+1Меня вот больше напрягает literally "@" вместо просто "@". Но зато действительно сложные регулярки, со всякими несъедающими группами, отрицаниями и переменными, может стать легче читать (а главное — редактировать).
nitso
01.09.2016 11:43Чуть выше уже оставлял ссылку: https://www.debuggex.com/r/xfu903DPxHkmoOpz
Очень помогает отлаживать сложные выражения.nitso
01.09.2016 11:56Ошибся веткой
dmitryredkin
01.09.2016 12:02+1Да, но он не транслирует обратно. С ним конечно легче найти ошибку, но если бы можно было редапктриовать саму схему — вот тогда был бы сервис.
dmitryredkin
01.09.2016 15:56Кроме того, заметил, что он показывает не все. Например, вопросик aka «non-gready capture» пропускается совсем.
dmitryredkin
31.08.2016 16:01+1Как уже было замечено выше, на самом деле нужен не компилятор regExp, а декомпилятор регулярок (как в сервисах визуализации в комментарии выше). И вот если бы оно умело работать в обе стороны — вот это было бы дело!
Ну реально: Вот вы бы отказались от такого сервиса?
kompi
01.09.2016 00:21Если хочется красоты, то можно использовать альтернативу — https://en.wikipedia.org/wiki/Parsing_expression_grammar. Использовал PEG в lua — довольно-таки удобно.
L0m
01.09.2016 00:21-1Прямо regex с человеческим лицом. Ожидаемо.
Вопрос насколько будет жизнеспособным, а это со временем увидим.
Athari
01.09.2016 01:07+2Классический сухой регекс:
/^(?:[0-9]|[a-z]|[\._%\+-])+(?:@)(?:[0-9]|[a-z]|[\.-])+(?:\.)[a-z]{2,}$/i
Это мусор, который генерирует библиотека что ли? Потому что в .NET я ручками написал бы так:
(?inx) ^ [ 0-9 a-z \._%\+- ] + @ [ 0-9 a-z \.- ] + \. [ a-z ] {2,} $
Ну и что более читаемо: это или ваша портянка?
viatro
01.09.2016 09:08Странно, что до сих пор никто не напомнил про эту статью:
Хватит писать регулярные выражения. Используйте вербальные выражения
vlreshet
Просто заменить символы на слова? А зачем? Тот кому понадобится работать с регулярками — и так знает синтаксис. Тот кто не знает — ему и не нужно, скорее всего. Да и куда такую простыню в коде девать? А подсветка как?
P.S. да и вообще, менять знаки на слова — у меня сразу возникают ассоциации с Turbo Pascal, и его begin, end…
igordata
Зачем — не знаю. Если работать через класс SLR, как в примере на ГитХабе, то будет и подсветка, и автокомплит в IDE.
x512
А то, что приятные глазу команды процессора в машинном коде заменены на всякие операторы и идентификаторы у вас неприятных ассоциаций не вызывает?)
vlreshet
Не то сравниваете. В ЯП высокого уровня, один знак/символ/слово заменяет целый набор машинных кодов. Мы просто присвоили переменной значение (пара символов кода) — а «под капотом» произошла уйма всего. А тут — прямая замена 1:1, никакого выигрыша по удобству.
fireSparrow
Читабельность важна.
Сам думал написать питоновский модуль для более приятной работы с регулярками, но пока руки не доходят.
Slipeer
ИМХО классическая регулярка читабельней и нагляднее.
Rastishka
Привычнее — да.
Читабельнее и нагляднее — вряд ли.
Halt
Во-первых, регулярные выражения можно разрывать комментариями. Во вторых, можно заводить метапеременные, которые использовать в выражениях.
stychos
Кстати да, для меня метапеременные совсем недавно оказались настоящим откровением.
thewizardplusplus
Подскажите, пожалуйста, что это за метапеременные такие? Пытался гуглить "regex metavars", но безрезультатно.
Судя по названию, это позволяет использовать куски регулярок несколько раз, чего очень и очень не хватает. Но я так и не смог найти, как такое можно сделать — обратные ссылки и именованные группы матчат лишь тот конкретный текст, который они сматчили в первый раз.
Или вы имеете ввиду определение переменных с кусками регулярок в самом языке, из которого они вызываются, а потом конструирование из них финального выражения через подстановку?
grossws
man 3 pcrepattern
, раздел subpatterns as subroutines.Регулярка типа
(sens|respons)e and \1ibility
даст совпадение в случаеsense and sensibility
иresponse and responsibility
, но неsense and responsibility
. Если же использовать(sens|respons)e and (?1)ibility
, то заматчится иsense and responsibility
.fedorro
А если бы изначально синтаксис регулярок был на словах, а сейчас предложили бы использовать символы — возникли бы ассоциации с Brainfuck?
Не обязательно в коде это пихать — можно препроцессор использовать и внешние файлы, да и подсветка есть.
smaugfm
Именно. Заменить символы на слова. Потому что люди воспринимают слова лучше чем символы. А мы ведь пишем код для людей а не для компьютера?
vintage
На самом деле люди мыслят образами. И правильно подобранные символы, позволяют быстрее считывать образ, чем чтение слов. Например, скобочки окружают некоторую область куда нагляднее, чем
begin..end
.Pinsky
скорее кобол уже
s-kozlov
А затем, что, хотя я сотни раз использовал регулярки, всё равно до сих пор каждый раз открываю доку, чтобы не перепутать хотя бы символы начала и конца строки. Вы же не будете утверждать, что они интуитивно понятны?
Gummilion
А я запомнил так, что на клавиатуре $ идет перед ^, а в регулярках наоборот: $ — конец, ^ — начало.
s-kozlov
Даже это контринтуитивно
punkkk
Для меня это как-то само собой разумеющееся. Хотя использовал регулярки не сотни раз.
Никогда не задумывался на счет этих символов. Может циркумфлекс ассоциируется так, что он не полностью занимает пространство символьное, а доллар на всю строку, и вроде даже больше других символов.
grossws
У меня caret (который вы назвали circumflex) ассоциируется с CR (
\r
).punkkk
Хех, мне когда то говорили, что это циркумфлекс… Жизнь не станет прежней.
grossws
Я был уверен, что circumflex — диакритический знак [1], [2], а не standalone. В современном unicode
u+5e
называетсяcircumflex accent
(ранее я его видел под именем ascii caret) [3], а caret — этоu+2038
[4].Извините за непреднамеренное разрушение мира ,)
punkkk
Да, я уже на вики глянул, там говорится, что циркумфлекс как раз для языковых особенностей, карет используется в ЯП, регулярках и прочем привычном применении.
Да ничего, всегда полезно узнать, где ошибался. :)