Чтение и запись Regex в виде простых английских предложений в Ruby с помощью Regexer

Все мы время от времени сталкиваемся с regex в процессе разработки программного обеспечения. Некоторые из распространенных вещей, которые мы делаем с regex, это поиск определенного набора строк или подстрок с общим шаблоном и создание собственной проверки пользовательского ввода.

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

Потому что, читая regex, кажется, что это язык с другой планеты. Он полон смеси символов и цифр, которые затем перемешиваются повсюду. Например, посмотрите на это:

/-?d+(.d*)?/
Войти в полноэкранный режим Выйти из полноэкранного режима

Приведенный выше regex предназначен для поиска любых положительных или отрицательных десятичных чисел. Для новичков в regex это действительно выглядит как что-то не с планеты Земля. Начинающим потребуется некоторое время, чтобы расшифровать этот потусторонний язык и даже создать свой собственный.

Поэтому, чтобы немного облегчить понимание и упростить создание, я создал рубиновый DSL под названием regexer, в котором они могут легко читать и писать regex с помощью простых английских слов и предложений. С точки зрения синтаксиса, он вдохновлен Factorybot & RSpec.

Начало работы

Для начала установите regexer gem

gem install regexer
Войдите в полноэкранный режим Выйти из полноэкранного режима

Мы создаем наши шаблоны regex, передавая блок, содержащий вызовы методов DSL, экземпляру класса PatternBuilder.

Для начала мы можем создать regex-шаблон, который будет соответствовать любой маленькой букве алфавита, следующим образом:

Regexer::PatternBuilder.new do
  has_letter from: "a", to: "z"
end

# generates /[a-z]/
Войти в полноэкранный режим Выйти из полноэкранного режима

Или мы можем создать регекс-шаблон, который будет соответствовать последовательным экземплярам слова «hello»:

Regexer::PatternBuilder.new do
  has_consecutive_instances_of 'hello'
end

# generates /(hello)+/
Войти в полноэкранный режим Выйти из полноэкранного режима

Приведенные выше примеры — это простое использование одного из доступных DSL-методов. Чтобы создать немного более сложные регекс-шаблоны, мы можем использовать цепочки DSL-методов и выражать их в простых предложениях. Вот пример:

Regexer::PatternBuilder.new do
  starts_with consecutive_instances_of letter from: "A", to: "Z"
end

# generates /^([A-Z]+)/
Войти в полноэкранный режим Выйти из полноэкранного режима

Как мы видим, это действительно читается как простое предложение.

Чтобы проверить сгенерированный шаблон regex, мы просто вызываем метод #result, который возвращает экземпляр Regexer::Model::Pattern, и мы можем просто вызвать метод #regex, чтобы получить значение regex.

pattern = Regexer::PatternBuilder.new do
  starts_with consecutive_instances_of letter from: "A", to: "Z"
end.result

puts pattern.regex
# Outputs /^([A-Z]+)/
Вход в полноэкранный режим Выход из полноэкранного режима

Как мы видим, для генерации regex ‘/^([A-Z]+)/’ в regexer, мы просто создали предложение, которое легче понять и функционирует почти аналогично тому, что мы хотим получить в regex.

Теперь, возвращаясь к более инопланетному шаблону regex, упомянутому во введении, мы можем выразить этот шаблон в regexer следующим образом

pattern = Regexer::PatternBuilder.new do
  has_none_or_one_instance_of "-"
  has_consecutive_instances_of digit_character
  has_none_or_one_instance_of group {
    contains "."
    has_none_or_consecutive_instances_of digit_character
  } 
end.result

puts pattern.regex
# Outputs /-?d+(.d*)?/
Войти в полноэкранный режим Выйти из полноэкранного режима

Сравнивая этот regex ‘/-?d+(.d*)?/’ и интерпретированный regexer выше, regexer просто сделал его более дружественным к человеку. Хотя он не совсем соответствует исходному шаблону regex, но технически, шаблон regex, сгенерированный regexer, функционирует так же, как и исходный regex.

Закрытие

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

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

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

Вы можете ознакомиться с gem-репо здесь: https://github.com/IvanIlagan/regexer-ruby.

У меня есть больше примеров возможных шаблонов regex, которые вы можете построить с помощью этого гема в репозитории. Также вы можете изучить больше
доступных методов DSL, чтобы вы могли смешивать и сопоставлять их и строить regex по своему усмотрению. Счастливого кодинга!

Оцените статью
devanswers.ru
Добавить комментарий