3

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.

1

4 Answers 4

6

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)/
3
  • 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, 2020 at 9:35
  • 1
    It worked! Using str2float is better for float number.
    – warem
    Jan 9, 2020 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, 2020 at 10:24
4

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.

2
  • In a data file, it could have many columns. So, by @user938271, \%V is more flexible.
    – warem
    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.
    – Hotschke
    Jan 9, 2020 at 13:06
2

: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)
1

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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