SRL — Simple Regex Language

Классический сухой регекс:

/^(?:[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, которая указана у него же в профиле. Видимо, это его же студия программистов, которые программируют за деньги. Желаю им удачи!

Similar posts

AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 73

    +8
    Просто заменить символы на слова? А зачем? Тот кому понадобится работать с регулярками — и так знает синтаксис. Тот кто не знает — ему и не нужно, скорее всего. Да и куда такую простыню в коде девать? А подсветка как?

    P.S. да и вообще, менять знаки на слова — у меня сразу возникают ассоциации с Turbo Pascal, и его begin, end…

      +3
      Зачем — не знаю. Если работать через класс SLR, как в примере на ГитХабе, то будет и подсветка, и автокомплит в IDE.
        +7
        А то, что приятные глазу команды процессора в машинном коде заменены на всякие операторы и идентификаторы у вас неприятных ассоциаций не вызывает?)
          +2
          Не то сравниваете. В ЯП высокого уровня, один знак/символ/слово заменяет целый набор машинных кодов. Мы просто присвоили переменной значение (пара символов кода) — а «под капотом» произошла уйма всего. А тут — прямая замена 1:1, никакого выигрыша по удобству.
          +1
          Читабельность важна.
          Сам думал написать питоновский модуль для более приятной работы с регулярками, но пока руки не доходят.
            +10
            ИМХО классическая регулярка читабельней и нагляднее.
              0

              Привычнее — да.
              Читабельнее и нагляднее — вряд ли.

              +2
              Во-первых, регулярные выражения можно разрывать комментариями. Во вторых, можно заводить метапеременные, которые использовать в выражениях.
              • UFO just landed and posted this here
                  0

                  Подскажите, пожалуйста, что это за метапеременные такие? Пытался гуглить "regex metavars", но безрезультатно.


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


                  Или вы имеете ввиду определение переменных с кусками регулярок в самом языке, из которого они вызываются, а потом конструирование из них финального выражения через подстановку?

                    +2

                    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.

                –1
                А если бы изначально синтаксис регулярок был на словах, а сейчас предложили бы использовать символы — возникли бы ассоциации с Brainfuck?
                Не обязательно в коде это пихать — можно препроцессор использовать и внешние файлы, да и подсветка есть.
                  +1
                  Именно. Заменить символы на слова. Потому что люди воспринимают слова лучше чем символы. А мы ведь пишем код для людей а не для компьютера?
                    +4

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

                    0
                    скорее кобол уже
                    • UFO just landed and posted this here
                        +1
                        А я запомнил так, что на клавиатуре $ идет перед ^, а в регулярках наоборот: $ — конец, ^ — начало.
                        • UFO just landed and posted this here
                          0
                          Для меня это как-то само собой разумеющееся. Хотя использовал регулярки не сотни раз.
                          Никогда не задумывался на счет этих символов. Может циркумфлекс ассоциируется так, что он не полностью занимает пространство символьное, а доллар на всю строку, и вроде даже больше других символов.
                            0

                            У меня caret (который вы назвали circumflex) ассоциируется с CR (\r).

                              0
                              Хех, мне когда то говорили, что это циркумфлекс… Жизнь не станет прежней.
                                0

                                Я был уверен, что circumflex — диакритический знак [1], [2], а не standalone. В современном unicode u+5e называется circumflex accent (ранее я его видел под именем ascii caret) [3], а caret — это u+2038 [4].


                                Извините за непреднамеренное разрушение мира ,)

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

                                  Да ничего, всегда полезно узнать, где ошибался. :)
                        –5

                        Сначала подумал, было, написать про «Владимирский астрал, эзотерика», но потом решил, что не буду.

                          +10
                          А почему нет? Мне нравится идея. Не думаю, что сам бы использовал, т.к. к регуляркам привык, но для новичков — вполне бы сгодилось.
                            +1
                            Ну видя код, который не работает и видя в нем регулярку. Насколько вы застреваете чтобы убедиться, что регулярка корректна?
                            +4
                            Картинку xkcd про единый стандарт уже постили?
                              0
                              Как средство обучения rx было бы, как мне кажется, вполне удобоваримо. Хотя для тех кто синтаксис уже освоил, вероятно будет неудобно.
                              • UFO just landed and posted this here
                                  0
                                  Относительно последнего утверждения, позволю себе с Вами не согласиться. RX — это инструмент, если он был создан — значит на то была причина, кто-то этим пользуется и получает то, что ожидает. Мне, к примеру, очень нравиться использовать данный инструмент и постижение его окупилось многократно в дальнейшем.
                                  • UFO just landed and posted this here
                                +3

                                Сайт не отвечает, видимо его постиг хабраэффект.


                                Для разъяснения и тестирования регекспов есть, например, отличный ресурс: https://regex101.com/
                                А вводить новый непонятный синтаксис регекспов — не слишком хорошая идея.

                                  +8
                                  Главная проблема регекспов в том, что они write-only. Описанный в статье подход эту проблему решает. Хотя любители однострочников на перле негодуют, да.

                                  Не знаю, буду ли использовать, но запомню, что существует.
                                    +9
                                    Проблема трудночитаемости регулярок решается так же, как проблема трудночитаемости обычного кода — выравниванием и комментариями. Во многих языках поддерживается, но, к сожалению — не во всех.
                                      –4
                                      Проблема чтения машинных кодов решается в выравнивании кода и расставлении комментариев. Но мы же не используем машинные коды правда?
                                        +12
                                        Синтаксис регулярных выражений — это уже мнемоническая надстройка над внутренним представлением, как ассемблер над машинными кодами. Предлагаемый в статье вариант не создает новый уровень абстракции, а просто заменяет одну строку на другую, более длинную — как если бы вместо mov ax, 0 пришлось писать set first register to value zero.
                                          –2
                                          Разница в том, что эту строку вполне сможет понять человек без предварительной подготовки (по крайней мере, после пары примеров).
                                          А регулярки читаются не сильно хорошо.
                                            +5
                                            Сложность понимания синтаксиса регулярок, имхо, преувеличена. На первый взгляд они выглядят пугающе, но по факту возможные элементы можно пересчитать по пальцам — группы, квантификаторы, альтернативы, штук пять спецсимволов и всякие редкие вещи типа опережающих проверок. Всё это можно запомнить за вечер, а с подсветкой синтаксиса становится еще проще. Так что всё упирается в сложность самого выражение — проверку email-адреса по RFC одинаково невозможно постичь в любой форме записи.

                                            Остается вопрос того, стоит ли доверять человеку без подготовки править код, руководствуясь наивным пониманием синтаксиса. Зачастую это чревато возникновением сложноуловимых багов — например, неопытный программист на C или JS может написать if(a = true) и долго удивляться, почему сравнение не работает, как надо.
                                    +6
                                    Пример в начале статьи совсем плох.
                                    Во-первых он уменьшается примерно раза в два, ликвидировав неиспользуемые группировки и объединив перечисления. Во-вторых, экранирование в перечислениях не нужно. И получается вполне читабельно:

                                    ^[0-9a-z._%+-]+@[0-9a-z.-]+\.[a-z]{2,}$

                                    И, наконец, Прекратите проверять Email с помощью регулярных выражений!

                                    После небольшой тренировки небольшие однострочные регулярки воспринимаются достаточно быстро. А вот словесный многострочный аналог требует больше времени для чтения.

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

                                    А есть специальные сервисы для визуализации regex

                                    В целом: за реализацию, конечно, жирный плюс, но, будет ли востребовано, покажет время. У меня сомнения.
                                      –5
                                      Проверка имейла регуляркой по большому счёту может быть сведена до /.+@.+/, но это же просто пример. Можете написать автору и предложить свой пример, заодно потестируете новую тулзу.
                                        +2
                                        Вы немного не уловили… Сократить регулярку != урезать. nitso сократил, а вы урезали. Хотя проверять email регулярными выражениями достаточно непрактично.
                                          +3
                                          Учитывая существование национальных доменов, я не могу сказать что проверка мыла на латинский алфавит имеет хоть малейший смысл…
                                      +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
                                      
                                        +1

                                        А можно ссылочку? А то гугл выдает только хип-хоп дуэт.

                                          +1
                                          https://habrahabr.ru/post/248147/ кажется это оно. Там есть раздел про этот grammar.tree

                                          Собственно ощущение что это и есть придумка господина vintage.
                                            0

                                            Да-да, это не готовое решение, а скорее идея, как можно было бы сделать лучше.

                                        • UFO just landed and posted this here
                                            0

                                            А какой символ порекомендуете для маркера начала сырых данных?

                                            • UFO just landed and posted this here
                                                0

                                                И я не раз повторял, что "=" — не разделитель "ключа" и "значения". Я согласен, что символ равенства вводит в заблуждение и было бы правильнее использовать какой-либо другой символ, например "|", но он в разных раскладках набирается разными способами, что несколько фрустирует.

                                                  0

                                                  Хотя, я тут подумал, из символов, набираемых одинаково в любой раскладке ("-", "_", "=", "+", "\") лучше подойдёт символ обратной косой черты. Он достаточно редкий в обычных данныхи используется в основном для похожей задачи — экранирования символов.

                                          +2
                                          Чего люди не придумают, лишь бы не учить регулярные выражения.
                                          А учить там — с гулькин нос, по факту.
                                            +2
                                            Никогда не пытался их учить, они слишком редко пригождаются, чтобы ими голову забивать, достаточно держать под рукой шпаргалку.
                                              0
                                              Шпаргалка — это понятно. Вопрос в том, насколько хорошо вы представляете, какие задачи решаются регулярными выражениями, а какие — нет.
                                            0
                                            По факту получили Builder для регулярок, что неплохо (и даже можно подумать про портировать на другие языки).
                                            Отдельный язык для такой задачи кмк перебор. Т.е. пока не ясно, как это использовать для самостоятельных задач.
                                              +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
                                                –2
                                                Уважения заслуживают такие люди, как автор этого языка, которые делают Своё.
                                                  +2
                                                  Зачем делать Своё, когда есть серьёзные и, главное, надёжные корпорации, которые сделают Своё лучше и быстрее? Если уже не сделали. Они же нам выдадут это бесплатно, в рамках рыночного планетарного прогрессорства.
                                                    0
                                                    Just For Fun
                                                      0

                                                      Затем, чтобы эти серьёзные и (главное!) надежные корпорации, взяли тебя на работу и ты делал Своё лучше и быстрее. :-D

                                                  • UFO just landed and posted this here
                                                      +4
                                                      Непонятен профит, это как обратный alias по сути, не очень комфортно. Регулярные выражения познаются не так сложно и не менее трудно читаются, дело легкой привычки.

                                                      Одно begin with, вместо циркумфлекса уже настораживает.
                                                        +1
                                                        Меня вот больше напрягает literally "@" вместо просто "@". Но зато действительно сложные регулярки, со всякими несъедающими группами, отрицаниями и переменными, может стать легче читать (а главное — редактировать).
                                                          0
                                                          Чуть выше уже оставлял ссылку: https://www.debuggex.com/r/xfu903DPxHkmoOpz
                                                          Очень помогает отлаживать сложные выражения.
                                                            0
                                                            Ошибся веткой
                                                              +1
                                                              Да, но он не транслирует обратно. С ним конечно легче найти ошибку, но если бы можно было редапктриовать саму схему — вот тогда был бы сервис.
                                                                0
                                                                Кроме того, заметил, что он показывает не все. Например, вопросик aka «non-gready capture» пропускается совсем.
                                                          +1
                                                          Как уже было замечено выше, на самом деле нужен не компилятор regExp, а декомпилятор регулярок (как в сервисах визуализации в комментарии выше). И вот если бы оно умело работать в обе стороны — вот это было бы дело!
                                                          Ну реально: Вот вы бы отказались от такого сервиса?
                                                            0
                                                            Попутал ветку и ответил в предыдущем комментарии.
                                                            0
                                                            Если хочется красоты, то можно использовать альтернативу — https://en.wikipedia.org/wiki/Parsing_expression_grammar. Использовал PEG в lua — довольно-таки удобно.
                                                              –1
                                                              Прямо regex с человеческим лицом. Ожидаемо.
                                                              Вопрос насколько будет жизнеспособным, а это со временем увидим.
                                                                +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,}
                                                                  $

                                                                Ну и что более читаемо: это или ваша портянка?

                                                                  0
                                                                  Странно, что до сих пор никто не напомнил про эту статью:
                                                                  Хватит писать регулярные выражения. Используйте вербальные выражения

                                                                  Only users with full accounts can post comments. Log in, please.