$1
, $2
, $3
... are Perl legacy. They are capture group variables, that is, they capture the groups inside the regular expression.
A named group is indicated by parentheses. So, the first capture group matches ([^\.])
, which is any non dot character, and (\..*)
matches a dot character \.
and any other characters after it.
Note that the second group is optional, so in the line below you have the ternary expression $2 ? $2 : ""
, which is a crypty-ish way to get either the value of the capture of a blank string.
The int, dec = $1, $2_or_blank_string
is a parallel assignment. Ruby supports assigning more than one variable at once, it's not different than doing int = $1.reversed
then dec = $2
So int
now holds the integer part (reversed) and dec
the decimal part of the number. We are interested in the first one for now.
The next empty while
does a string substitution. The method gsub! replaces all occurences of the regular expression for the value in the seconf argument. But it returns nil
if no change happened, which ends the while
.
The /(,|\.|^)(\d{3})(\d)/
expression matches:
(,|\.|^)
A comma, a point or the beginning of the string
(\d{3})
Three digits
(\d)
A fourth digit
Then replaces it for \1\2,\3
. The \n
in a string substitution mean the nth capture group, just as the $n
variables do. So, it basically does: if I have four digits, just add a comma after the third one. Repeat until no group of four digits is found
Then, just reverse the integer part again and append the decimal part.