80

Vim is pretty powerful when editing by line - the search/replace tools are modeled to work linewise.

But what if I want to change a particular column across all lines? For example, how can I change the 80th column in my file to a # easily?

Lazer
  • 90,700
  • 113
  • 281
  • 364

6 Answers6

159

To edit a column, follow these steps:

  1. Stand on the beginning of the column
  2. Press Ctrl+v, then mark across the column you want to edit.
  3. Press Shift+i to insert text at the beginning of the column, Shift+a to append text, r to replace highlighted text, d to delete, c to change... etc.
  4. Hit ESC when done.

I think people (me) sometimes map the column editing keys to Ctrl+Q so it won't collide with visual select line (V) or paste-text if you mapped it as such.

NReilingh
  • 1,730
  • 17
  • 32
sa125
  • 28,121
  • 38
  • 111
  • 153
  • 5
    [Ctrl]+[V] is block-wise visual mode, which @Lazer described as "messy" in response to my answer. This would be my preferred way to do it (using [r] to replace the column with '#'), but the OP has indicated this to be unacceptable. – johnsyweb Aug 07 '11 at 10:56
  • 1
    @Johnsyweb I thought he meant visual select and then search and replace on the selection using regex, which I find messy (and unnecessary) as well. I don't see why column mode is bad here, but then again I'm not familiar with the OP's code. He could also record a macro and re-run it X times, but that's still more work than column editing. – sa125 Aug 07 '11 at 11:01
  • 2
    I agree with you this is the neatest way to work and perhaps future visitors to this question will find this useful, so you get an up-vote from me. – johnsyweb Aug 07 '11 at 11:05
  • 2
    ctrl-V and ctrl+A didn't work for me, I (shift-i) and A (shift-a) did, r, d, and c worked as expected. – user160917 Dec 30 '14 at 21:43
  • 2
    I need to hit twice ESC to get things done. And when I press shift+i to insert text, it only shows change in the first line but eventually all selected lines will change. – xi.lin Dec 29 '15 at 03:50
  • Hi @sa125 best answer ever – Andy K Jun 22 '16 at 13:54
58

...I couldn't follow the steps of sa125 (facepalm) so I looked someplace else and found a simpler explanation at: https://blog.pivotal.io/labs/labs/column-edit-mode-in-vi

  1. Ctrl+v [ and select what ever you want]
  2. Shift+i [and write whatever...(check out ** below)]
  3. Esc

*c without Shift can be used instead of step 2, to delete selection before insert. And also r to replace.

**!! Attention Don't be discouraged by the fact that only the first row is changed when you 'write whatever...'!!

Hope it helps!

44

You can use a substitution where the pattern matches a specific column (\%c):

:%s/\%80c/#/<CR>

Or you can use block-wise visual mode:

gg80|CTRL+vGr#

The 'virtualedit' option can be used to allow positioning the cursor to positions where there is no actual character:

:set virtualedit
johnsyweb
  • 136,902
  • 23
  • 188
  • 247
  • visual mode is messy.. is there an easier way to say `replace 80th column with #`? – Lazer Aug 07 '11 at 09:45
  • 1
    @Lazer: Have updated my answer to prefer a `:s` approach (but blockwise visual mode will save you three key-presses!) – johnsyweb Aug 07 '11 at 09:56
  • Note that for the block-wise visual mode solution, it would be `79l` to get to the 80th column, not `80l`, because you're starting in column 1. (Or alternatively a better solution, `80|` - 8, 0, pipe) – Chris Morgan Aug 07 '11 at 11:11
  • @Chris: The [pipe](http://vimdoc.sourceforge.net/htmldoc/motion.html#bar) character (which I have used) takes you to the column regardless of your start position. You're right, though, [`79l`](http://vimdoc.sourceforge.net/htmldoc/motion.html#l) (ell) will work just as well without extra keystrokes. – johnsyweb Aug 07 '11 at 11:15
  • @Johnsyweb: whoops, apparently I didn't look quite closely enough... I thought you had used `l` rather than `|` :-/ – Chris Morgan Aug 07 '11 at 11:25
  • 1
    Actually, visual block mode only works if you already have text in the desired column. Therfore, the :%s option may be the only one that will work regardless of the existing text. It's really great for "flower-boxing" (what the OP was asking about) or for any situation where you have some ragged-right text and want to force some data into a column that extends past the longest line. – JESii Jul 28 '14 at 21:03
  • @JESii: Thanks for pointing that out. I've updated my answer to include `:set ve`, which I think addresses your concern. – johnsyweb Jul 29 '14 at 06:37
  • @Downvoter: how would you recommend I improve this answer? – johnsyweb Oct 15 '15 at 20:28
  • Your answer, while relevant to the OP's particular example, appears comparatively insane to the one below and is not useful when I arrive from google – xavier Oct 19 '15 at 08:02
  • Minor nitpick: The `virtualedit` option isn't a boolean, as the provided example suggests, at least not as of Vim 8.1. It can be set to `block`, `insert`, `all`, or `onemore` (see the linked help for the available options). – Soren Bjornstad Oct 19 '19 at 21:25
1

For column-wise editing, vis.vim is really useful. You can block-select your column of interest, and manipulate it with normal commands, and even arbitrary Ex commands. From the example on that page, I have often used the pattern:

:'<,'>B s/abc/ABC/g

You can Vundle/Pathogen install vis.vim from github:

Plugin 'taku-o/vim-vis'

Micah Elliott
  • 9,600
  • 5
  • 51
  • 54
1

I may be totally off topic here, but if your idea is to avoid long lines, you could have a look at the colorcolumn option of vim 7.3.

Plouff
  • 3,290
  • 2
  • 27
  • 45
1

To remove all # in the example below.

  1. ctrl + v at # : (Visual Block) mode
  2. drag all # s using arrow down or j
  3. Then press x to remove all # s
# a
# b
# c
# d
# e
# f
  1. Then press Esc to escape from editing
 a
 b
 c
 d
 e
 f
suno3
  • 31
  • 3
  • Thank you for providing an answer. However, the question was how to add a `#` in column 80, not how to remove it from column 1. – Friedrich Apr 06 '23 at 06:58