Vim Tips Wiki
(reword; add examples and explanation)
VimLover (talk | contribs)
m (Correction of the search pattern in the substitute command : added \+)
Tag: Visual edit
 
(7 intermediate revisions by 5 users not shown)
Line 11: Line 11:
 
|category2=
 
|category2=
 
}}
 
}}
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 <tt>$</tt> ($10+$20). This version only handles unsigned integers.
+
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 <code>$</code> ($10+$20). This version only handles unsigned integers.
   
 
==Sum function==
 
==Sum function==
Line 23: Line 23:
 
</pre>
 
</pre>
   
In Vim, you could copy the above lines then type <tt>:@"</tt> 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]].
+
In Vim, you could copy the above lines then type <code>:@"</code> 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 <tt>S</tt>. The function returns the given number so that it can be used in a substitute command without changing the number.
+
The function adds the given number onto the sum in the global variable <code>S</code>. The function returns the given number so that it can be used in a substitute command without changing the number.
   
 
==Usage==
 
==Usage==
Line 38: Line 38:
 
You can add the numbers with these commands:
 
You can add the numbers with these commands:
 
<pre>
 
<pre>
:let S=0
+
:let g:S=0
 
:%s/\d\+/\=Sum(submatch(0))/
 
:%s/\d\+/\=Sum(submatch(0))/
:echo S
+
:echo g:S
 
</pre>
 
</pre>
   
 
The first line clears the variable used to hold the sum. The third line displays the sum.
 
The first line clears the variable used to hold the sum. The third line displays the sum.
   
The substitute replaces the first occurrence of <tt>\d\+</tt> (one or more digits) on each line. The replacement <tt>\=</tt> is the result of the expression <tt>Sum(submatch(0))</tt> which calls the <tt>Sum()</tt> function. The <tt>submatch(0)</tt> is the text matched by the search pattern (the number which was found).
+
The substitute replaces the first occurrence of <code>\d\+</code> (one or more digits) on each line. The replacement <code>\=</code> is the result of the expression <code>Sum(submatch(0))</code> which calls the <code>Sum()</code> function. The <code>submatch(0)</code> is the text matched by the search pattern (the number which was found).
   
 
Using the following would include all numbers in each line:
 
Using the following would include all numbers in each line:
Line 52: Line 52:
 
</pre>
 
</pre>
   
This adds only the numbers following a <tt>$</tt> character (the <tt>\zs</tt> starts the search hit after the <tt>$</tt> is found):
+
This adds only the numbers following a <code>$</code> character (the <code>\zs</code> starts the search hit after the <code>$</code> is found):
 
<pre>
 
<pre>
 
:%s/\$\zs\d\+/\=Sum(submatch(0))/g
 
:%s/\$\zs\d\+/\=Sum(submatch(0))/g
Line 61: Line 61:
 
:%s/.*\zs\d\+/\=Sum(submatch(0))/
 
:%s/.*\zs\d\+/\=Sum(submatch(0))/
 
</pre>
 
</pre>
 
 
==References==
 
==References==
 
*{{help|:s}}
 
*{{help|:s}}
 
*{{help|pattern}}
 
*{{help|pattern}}
  +
*{{help|usr_27.txt}}
+
{{help|usr_27.txt}}
  +
 
*{{help|sub-replace-special}}
 
*{{help|sub-replace-special}}
   
 
==Comments==
 
==Comments==
If you want to replace the numbers in the file with a running total, in the <tt>Sum()</tt> function, replace:
+
If you want to replace the numbers in the file with a running total, in the <code>Sum()</code> function, replace:
 
<pre>
 
<pre>
 
return a:number
 
return a:number
Line 77: Line 78:
 
return g:S
 
return g:S
 
</pre>
 
</pre>
  +
  +
===Floats===
  +
Float numbers could be handled easily:
  +
<pre>
  +
:%s/\d\+/\=Sum(str2float(submatch(0)))/g
  +
</pre>
  +
: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. [[User:JohnBeckett|JohnBeckett]] ([[User talk:JohnBeckett|talk]]) 06:13, September 9, 2014 (UTC)
  +
:
  +
:It does work for me as follows :
  +
:<span lang="en" dir="ltr">In</span> .vimrc I have :<syntaxhighlight lang="vim">
  +
let g:S = 0
  +
function! Sum(number)
  +
let g:S = g:S + str2float(a:number)
  +
return a:number
  +
endfunction
  +
</syntaxhighlight>
  +
:Usage :
  +
:<syntaxhighlight lang="vim">
  +
:let g:S=0
  +
:%s/[0-9\.]\+/\=Sum(submatch(0))/
  +
:echo g:S
  +
</syntaxhighlight>

Latest revision as of 22:53, 20 December 2020

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[]

:help usr_27.txt

Comments[]

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