Mobidi
Mobidi

Reputation: 95

Complex regex in ruby

I have a complex regex to make in ruby.

str = '1:2-2:1015-3:1007,=,0-4:2,|,3'
regex = /(\d+):|(\d+),\|,(\d+)/

My goal is to find only certain digits (those before ':' for example) and add a number to all of them.

Example: if I want to add 20 to all of them, my str would look like this :

str = '21:2-22:1015-23:1007,=,0-24:22,|,23'

I can find them with this regex, but I can't find how to make an addition.

I tried a few things like this :

str.gsub(/(\d+):/){|m| m.to_i + 30}
Result : "312-321015-331007,=,0-3432" 

It deleted the ':', the '|', and didn't make the addition for the last digit.

I'm sure I'm doing it wrong. Perhaps with map, and scan I could do something right?

Thanks for your help, I hope my explanations are clear.

Edit : The two solution bellow are correct for me, do not hesitate to read both of them

Upvotes: 2

Views: 189

Answers (2)

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121000

There is a lot easier way:

▶ str = '1:2-2:1015-3:1007,=,0-4:2,|,3'
▶ regex = /\d+(?=:)|\d+(?=,\|,\d)|(?<=\d,\|,)\d+/
▶ str.gsub(regex) { |m| (m.to_i + 20).to_s }
#⇒ "21:2-22:1015-23:1007,=,0-24:22,|,23"

The trick here is that we match digits only to make them easy to subst. Positive lookaheads help to catch those digits (note, that there are now 3 different conditions, to always match the single number.)

Upvotes: 1

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626747

Your last regex does not match the (\d+),\|,(\d+) pattern you had in the original pattern. Note that since you already match : and ,|,, you need to reinsert them in the replacement. Also, what is more important, you only need to apply addition to the captured values, not the whole matched text.

Use something like

str = '1:2-2:1015-3:1007,=,0-4:2,|,3'
regex = /(\d+):|(\d+),\|,(\d+)/
toadd  = 20
puts str.gsub(regex) { $~[2] ? "#{$~[2].to_i + toadd},|,#{$~[3].to_i + toadd}" : "#{$~[1].to_i + toadd}:" }

See the online demo

You need to check if Group 2 ($~[2]) matched first, and if yes, only perform addition to groups 2 and 3, and if not, only add to Group 1 ($~[1]) contents.

Upvotes: 2

Related Questions