Reputation: 95
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
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
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