We all encounter regex from time to time throughout our software development. Few of the common things we do with regex is wanting to find a certain set of strings or substrings with a common pattern and making our own custom validation of user inputs.
But us we stumble upon regex, you'll be most likely be eyes wide open and scratching your head on it while trying to read and understand it. Well, at least that's what I always do and most likely for people who haven't have much experience with regex.
Because reading regex, it feels like a language from another planet. It's full of a mix of characters and numbers then jumbled up all over the place. Like look at this for example:
/-?\d+(\.\d*)?/
The regex above is for matching any positive or negative decimal numbers. For beginners in regex, this really looks like something not from planet Earth. It will take a while for beginners to decipher this otherworldly language and even create their own.
So to make it a bit easier to understand and easier to create one, I created a ruby DSL called regexer in which they can easily read and write regex with just simple english words and sentences. Syntax-wise, it is inspired by Factorybot & RSpec.
Getting Started
To start, install regexer gem
gem install regexer
We build our regex patterns by giving a block that contains DSL method calls to the instance of PatternBuilder class.
For starters, we can create a regex pattern that matches any small letter in the alphabet like so:
Regexer::PatternBuilder.new do
has_letter from: "a", to: "z"
end
# generates /[a-z]/
Or we can create a regex pattern that matches consecutive instances of the word 'hello':
Regexer::PatternBuilder.new do
has_consecutive_instances_of 'hello'
end
# generates /(hello)+/
The above examples are just simple usages of one of the available DSL methods. To make a slightly bit more complex regex patterns, we can actually chain DSL methods and express it into simple sentences. Here's an example:
Regexer::PatternBuilder.new do
starts_with consecutive_instances_of letter from: "A", to: "Z"
end
# generates /^([A-Z]+)/
As we can see, it actually reads as a simple sentence.
In order for us to check the regex pattern that it generated, we just call the #result method so that it will return a Regexer::Model::Pattern instance and we can just call the #regex method to get the regex value.
pattern = Regexer::PatternBuilder.new do
starts_with consecutive_instances_of letter from: "A", to: "Z"
end.result
puts pattern.regex
# Outputs /^([A-Z]+)/
As we can see, to generate the regex '/^([A-Z]+)/' in regexer, we just made a sentence that is easier to understand and functions almost similar to what we want in regex.
Now going back to the more alien like regex pattern mentioned in the introduction, we can actually express that pattern in regexer like so
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*)?/
So comparing this regex '/-?\d+(.\d*)?/' and the regexer interpreted one above, regexer just made it feel more human friendly. Though it didn't exactly match the raw regex pattern but technically, the regex pattern generated by regexer functions the same as with the raw regex.
Closing
This is my very first ruby gem and first time in making my own DSL hehe. Though there are some others who have a similar gem and works to build more complex patterns and still be human readable. But despite that, I am happy to release this and had fun on making a DSL with ruby hehe.
So far, the current state of regexer allows simple to a slightly bit more complex regex patterns be generated in a more readable format. But soon enough, I'll be adding more functionality so that it can build more complex regex patterns and still retain its simple english sentence structure.
Hopefully this ruby DSL can at least make it easier to read and understand regex especially for beginners.
You can checkout the gem repo here: https://github.com/IvanIlagan/regexer-ruby
I have more examples of possible regex patterns that you can build using the gem in the repo. Also you can explore more of
the available DSL methods for you guys to mix and match and build regex more sentence like for your needs. Happy coding!
Top comments (0)