# What is the replace regexp string for applying 3 digit grouping to any number?

the title gives it all away:

I want this

`9874599842006432.08`

To become this

`9,874,599,842,006,432.08`

with 1 single replace regexp operation and flexible, so that the same string also would work on a shorter or longer number like for example 10777524,62 .

I've worked really hard on figuring it out, including turning to manuals and tutorials, but sadly in vein.

Example 1: The closed I could come up with is this here, where I simplified by expressing 3 digit groups with a simple letter from the alphabet, to have it easier to understand what I'm doing there.

`Query replace regexp (default \([0-9]\)\(n\)\(n\)\(n\)\(n\)\(n\)\(.\) -> \1,\2,\3,\4,\5,\6\7)`

The idea: Grouping all 3 digit groups separately and referably, then replacing the whole match by reconstruction of it extended by desired changes - possible by spliting all relevant parts up in grouping constructs with round brackets.

But the problem is: It's fixed. Give the string a number with 5 n's - it works. Give it a smaller number, like for example, with just 3 n's - and it fails by not detecting it for a replace operation.

Example 2: Another example

`Query replace regexp (default \([0-9]\)\(n\)\(.\) -> \1,\2\3):`

Turns

`1n.07`

into

`1,n.07`

Nice. But what about bigger numbers? Dealing with just 1 n is hard-wired into the string.

And what about applying '*' into it?

Giving a string like

`1nnn.57`

`Query replace regexp (default \([0-9]\)\(n*\)\(.\) -> \1,\2\3):`

At least grabs the relevant part in one operation, no matter how many n's are part of it,

`1nnn.`

But instead of turning it into this

`1,n,n,n.57`

its output is this

`1,nnn.57`

So, you see: Regarding the finding part, it is capable to detect any number, no matter how many n's it consists of, but regarding the replacing part, it fails to apply the modification not just for 1 n, but for all n's it detected by * - here 3 times at once.

Any better ideas?

• It sounds like you're trying to find a single-pass solution to a problem which necessitates multiple passes, and inevitably failing. Unless you hard-code the number of sub-groups or use elisp in the replacement, I don't see how a single search/replace could achieve this. You need to match the digits first, and then iterate over the matches to add each of the commas. Commented Jan 31, 2023 at 22:55

I am not sure about your use-case, but anyway I would recommend using any of the methods mentioned in this reddit post.

So, if you'd like to 'commify' all numbers in some buffer, then you could use the add-number-grouping function from the Emacs wiki, and create a custom function to replace all numbers in a buffer as follows:

``````(defun add-number-grouping (number &optional separator)
"Add commas to NUMBER (a string) and return it as a string.
Optional SEPARATOR is the string to use to separate groups.
It defaults to a comma."
(let ((op (or separator ",")))
(while (string-match "\\(.*[0-9]\\)\\([0-9][0-9][0-9].*\\)" number)
(setq number (concat
(match-string 1 number) op
(match-string 2 number))))
number))

(defun commify-numbers ()
(interactive)
(while (search-forward-regexp " \\([0-9][0-9.]+\\)" nil t)
(let ((from (match-beginning 1))
(to (match-end 1))
;; bind match-data now as it gets updated by calling
Note that here the `add-number-grouping` function has been modified to work on a (number-)string (instead of a number directly).