# Substitute figure by math

I have a file like this:

``````1 2 3
4 5 6
7 8 9
0 1 2
``````

I want to change a block-wise visual selection area, e.g. `5` and `8`. I want to substitute them by multiplying the figures by `0.7` and I want to round to 3 digits, e.g. `5` changed to `3.500`.

I know `submatch` can work the math, but I don’t know how to define the grouped part.

You could try this:

``````:'<,'>s/\%V\d*\%V\d/\=printf('%.3f', str2nr(submatch(0))*0.7)/
``````

• `:h /\%V`
• `:h printf()`

Figure could be 5, 5.0, 5.00 or 5.000, 12345678.000, 3 digits at most. How can we define a more general grouped part?

Try a more permissive pattern:

``````:'<,'>s/\%V\d*\.\=\d*\%V\d/\=printf('%.3f', str2float(submatch(0))*0.7)/
``````
• Figure could be 5, 5.0, 5.00 or 5.000, 12345678.000, 3 digits at most. How can we define a more general grouped part? Jan 9, 2020 at 9:35
• It worked! Using `str2float` is better for float number. Jan 9, 2020 at 10:03
• For easily using, `:vmap <leader>zz :s/\%V\d*\.\=\d*\%V\d/\=printf('%.3f', str2float(submatch(0))*0.7)/`. After block selection, `\zz` if `<leader>` is `\`, change 0.7 to whatever, then enter. Jan 9, 2020 at 10:24

### Visual Block: Colon commands will still apply to whole lines

You find in the user manual section 10.3 'Command ranges' following note (almost at the end of `:h 10.3`:

Note: When using Visual mode to select part of a line, or using CTRL-V to select a block of text, the colon commands will still apply to whole lines. This might change in a future version of Vim.

A substitute command operating on the whole line would look like

``````:'<,'>s/\(\d*\s*\)\(\d*\)\(\s*.*\)/\=printf('%d %.3f %d', submatch(1), str2nr(submatch(2))*0.7, submatch(3))
``````

Alternative, filter lines through `awk`:

``````:'<,'>!awk '{printf "\%d \%.3f \%d\n", \$1, \$2*0.7, \$3}'
``````

### `\%V`

Please note the answer by @user938271 using the special atom `\%V` in a pattern. This circumvents the limitation that colon commands work always on whole lines for the `:substitute` command.

• In a data file, it could have many columns. So, by @user938271, `\%V` is more flexible. Jan 9, 2020 at 9:53
• I learned the `\%V` atom today myself. I can agree with people who say that learning vim is a long journey. After 10 years of vim usage I did not know this one. Jan 9, 2020 at 13:06

### `:B` from plugin vis.vim by DrChip: `:B s/pattern/becomes/`

This plugin provides a general command to make all colon commands to operate only on the visual block selection:

``````:'<,'>B s/\d*/\=printf('%.3f', str2nr(submatch(0))*0.7)
``````

### `:Substitute` for visual block from plugin csv.vim

For single-space separated data you have to initialize the plugin csv.vim manually as following:

``````\$ vim mydata
:setf csv
:let g:csv_delim=' '
:CSVInit
``````

Now you can use the `:Substitute` command:

Select part of a column with a visual block (e.g. `5\n8`) and then run

``````:'<,'>Substitute \d*/\=printf('%.3f', str2nr(submatch(0))*0.7)
``````