I recently ran into a weird issue in code that resulted in a long number not being formatted the way I was expecting.

The code was expected to take a long string of numbers, and format them in a pre-defined way.

num_string = "123234345456567678789890901012"
num_string.length  \\ 30

In this case, we want to break this into groups of 3 digits. The expected result would be:

"123-234-345-456-567-678-789-890-901-012"

The regular expression uses 10 capture groups to perform the formatting:

num_string.sub(/(\d{3})(\d{3})(\d{3})(\d{3})(\d{3})(\d{3})(\d{3})(\d{3})
(\d{3})(\d{3})/, '\1-\2-\3-\4-\5-\6-\7-\8-\9-\10')

The issue is that the output of this is:

"123-234-345-456-567-678-789-890-901-1230"

The difference is subtle, which is probably why we didn’t detect it earlier. if you look at the last replacement group, it actually users capture group 1 again, followed by the literal “0” instead of the tenth capture group.

As it turns out, Ruby only supports capture groups 0-9 in this style.