1,646 Pages

Tip 205 Printable Monobook Previous Next

created 2002 · complexity intermediate · author Stanislav Sitar · version 6.0

Here is how to calculate the sum of all numbers matching some pattern, for example, the first number on each line with a number, or the numbers following a `\$` (\$10+\$20). This version only handles unsigned integers.

## Sum function

First, define the following function.

```let g:S = 0  "result in global variable S
function! Sum(number)
let g:S = g:S + a:number
return a:number
endfunction
```

In Vim, you could copy the above lines then type `:@"` to execute the copied lines (to define the function). Or, you could put the code in a file in your plugin directory, or in your vimrc.

The function adds the given number onto the sum in the global variable `S`. The function returns the given number so that it can be used in a substitute command without changing the number.

## Usage

Suppose you have this text:

```Here are some items:
Take 10 apples
and 20 pears
then 30 walnuts.
```

You can add the numbers with these commands:

```:let g:S=0
:%s/\d\+/\=Sum(submatch(0))/
:echo g:S
```

The first line clears the variable used to hold the sum. The third line displays the sum.

The substitute replaces the first occurrence of `\d\+` (one or more digits) on each line. The replacement `\=` is the result of the expression `Sum(submatch(0))` which calls the `Sum()` function. The `submatch(0)` is the text matched by the search pattern (the number which was found).

Using the following would include all numbers in each line:

```:%s/\d\+/\=Sum(submatch(0))/g
```

This adds only the numbers following a `\$` character (the `\zs` starts the search hit after the `\$` is found):

```:%s/\\$\zs\d\+/\=Sum(submatch(0))/g
```

This adds only the last number on each line that contains a number:

```:%s/.*\zs\d\+/\=Sum(submatch(0))/
```

## References

If you want to replace the numbers in the file with a running total, in the `Sum()` function, replace:

```  return a:number
```

with

```  return g:S
```

### Floats

Float numbers could be handled easily:

```:%s/\d\+/\=Sum(str2float(submatch(0)))/g
```
The above does not work because the search pattern only finds unsigned integers. Also I do not think str2float is needed. This might be fixed and moved back into the tip. JohnBeckett (talk) 06:13, September 9, 2014 (UTC)
It does work for me as follows :
In .vimrc I have :
```let g:S = 0
function! Sum(number)
let g:S = g:S + str2float(a:number)
return a:number
endfunction
```
Usage :
```:let g:S=0
:%s/[0-9\.]\+/\=Sum(submatch(0))/
:echo g:S
```
Community content is available under CC-BY-SA unless otherwise noted.