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)/

For more info, see:

  • :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)/
| improve this answer | |
  • 1
    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? – warem Jan 9 at 9:35
  • 1
    It worked! Using str2float is better for float number. – warem Jan 9 at 10:03
  • 1
    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. – warem Jan 9 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}'


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.

| improve this answer | |
  • In a data file, it could have many columns. So, by @user938271, \%V is more flexible. – warem Jan 9 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. – Hotschke Jan 9 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)
| improve this answer | |

: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=' '

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)
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.