anyone can help me?
I have a string with format: 10 mins - 20 mins
OR 1 min - 10 mins
OR 10 mins - 1 hour
OR 10 mins - 1 hour 30 mins
OR 10 mins - 2 hours
OR 10 mins - 2 hours 30 mins
.
I wanna create a regex for all formats but I can't :disappointed: . Please help me, thanks a lot.
A regex possible with all above formats.
CodePudding user response:
I might split on the dash first, then match out the components in each side using the same regular expression.
E.g.
"1 hour 10 mins - 3 hours".split(/\s -\s /, 2).map do |s|
s.scan(
/
\d \s mins
| \d \s hour(?=s?)
| \d \s hour(?=s?)
\s
\d \s min(?=s?)
/x
)
end
# => [["1 hour", "10 mins"], ["3 hour"]]
"1 hour 10 mins - 40 mins".split(/\s -\s /, 2).map do |s|
s.scan(
/
\d \s mins
| \d \s hour(?=s?)
| \d \s hour(?=s?)
\s
\d \s min(?=s?)
/x
)
end
# [["1 hour", "10 mins"], ["40 mins"]]
CodePudding user response:
I've assumed:
- every string contains only minutes (not hours) to the left of the minus sign; and
- hours, where present, are between 1 and 9.
One can then use String#match and MatchData#named_captures with the regular expression
rgx = /(?<lmin>(?:[1-9]|[1-5]\d)) mins? \- (?:(?<hr>[1-9]) hours?(?: (?<rminwhr>\g<lmin>) mins?)?|(?<rminwohr>\g<lmin>) mins?)/
to extract the values of interest. Let's try it for the examples given in the question.
["10 mins - 20 mins",
"1 min - 10 mins",
"10 mins - 1 hour",
"10 mins - 1 hour 30 mins",
"10 mins - 2 hours",
"10 mins - 2 hours 30 mins"].each do |str|
m = str.match(rgx)
puts str
puts "str.match(rgx) = #{m}"
puts "captures = #{m.named_captures}"
puts
end
displays the following.
10 mins - 20 mins
str.match(rgx) = 10 mins - 20 mins
captures = {"lmin"=>"20", "hr"=>nil, "rminwhr"=>nil, "rminwohr"=>"20"}
1 min - 10 mins
str.match(rgx) = 1 min - 10 mins
captures = {"lmin"=>"10", "hr"=>nil, "rminwhr"=>nil, "rminwohr"=>"10"}
10 mins - 1 hour
str.match(rgx) = 10 mins - 1 hour
captures = {"lmin"=>"10", "hr"=>"1", "rminwhr"=>nil, "rminwohr"=>nil}
10 mins - 1 hour 30 mins
str.match(rgx) = 10 mins - 1 hour 30 mins
captures = {"lmin"=>"30", "hr"=>"1", "rminwhr"=>"30", "rminwohr"=>nil}
10 mins - 2 hours
str.match(rgx) = 10 mins - 2 hours
captures = {"lmin"=>"10", "hr"=>"2", "rminwhr"=>nil, "rminwohr"=>nil}
10 mins - 2 hours 30 mins
str.match(rgx) = 10 mins - 2 hours 30 mins
captures = {"lmin"=>"30", "hr"=>"2", "rminwhr"=>"30", "rminwohr"=>nil}
One can see a demonstration of the regular expression here. Hover the cursor over the regular expression to see an explanation of the function of each part of the expression. These results are shown for the PCRE regex engine but they are the same for Ruby's regex engine (Oniguruma).