Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access the results of .match as string value in Crystal lang

In many other programming languages, there is a function which takes as a parameter a regular expression and returns an array of string values. This is true of Javascript and Ruby. The .match in crystal, however, does 1) not seem to accept the global flag and 2) it does not return an array but rather a struct of type Regex::MatchData. (https://crystal-lang.org/api/0.25.1/Regex/MatchData.html)

As an example the following code:

str = "Happy days"
re = /[a-z]+/i
matches = str.match(re)
puts matches

returns Regex::MatchData("Happy")

I am unsure how to convert this result into a string or why this is not the default as it is in the inspiration language (Ruby). I understand this question probably results from my inexperience dealing with structs and compiled languages but I would appreciate an answer in hopes that it might also help someone else coming from a JS/Ruby background.

like image 627
Shadow43375 Avatar asked Sep 02 '25 15:09

Shadow43375


1 Answers

What if I want to convert to a string merely the first match?

puts "Happy days"[/[a-z]+/i]?
puts "Happy days".match(/[a-z]+/i).try &.[0]

It will try to match a string against /[a-z]+/i regex and if there is a match, Group 0, i.e. the whole match, will be output. Note that the ? after [...] will make it fail gracefully if there is no match found. If you just use puts "??!!"[/[a-z]+/i], an exception will be thrown.

See this online demo.

If you want the functionality similar to String#scan that returns all matches found in the input, you may use (shortened version only left as per @Amadan's remark):

str = "Happy days"
re = /[a-z]+/i
matches = [] of String
str.scan(re) do |match|
      matches << match[0]
    end
puts matches

Output of the code above:

["Happy", "days"]

Note that String::scan will return an array of Regex::MatchData for each match. To get the text of the match, just access the first item in the match object.

A shorter way is to use

matches = str.scan(re).map(&.to_a).flatten

See the online demo.

like image 104
Wiktor Stribiżew Avatar answered Sep 05 '25 12:09

Wiktor Stribiżew