3

How do I delete the last 3 words from every line in Vim by using a single command or by using a recording?

For example, before,

10 3 -5 6 1 0 5 
5 9 -1 0 56 8 9
-6 0 45 8 6 3 0

After,

10 3 -5 6  
5 9 -1 0 
-6 0 45 8 
Sam
  • 7,252
  • 16
  • 46
  • 65
imbichie
  • 1,510
  • 3
  • 13
  • 23

4 Answers4

8

Your safest bet would be:

:%norm $3gElD

Explanation:

For all lines in the file (%), in normal mode (norm), move to the end of the line ($), then 3 WORDs backward (3gE), one character to the right (l), and delete the characters under the cursor until the end of the line.

The reason for gE is to tell VIM to move in terms of what it defines as a WORD: a sequence of non-blank characters, separated with white space (including the dash).

EDIT: In case there's trailing whitespace in a line, the above will fail. You can first get rid of all trailing whitespace in a file with :%s/\s*$//g

Michael Foukarakis
  • 39,737
  • 6
  • 87
  • 123
2

You can use this command:

:%norm $3F D

edit

@balintpekker is right that this command only assumes one single space between word.

@MichaelFoukarakis's solution is more generic, as it supports variable numbers of spaces and tabs but it fails on the first line of the given sample because it has a trailing space, forcing you to issue a second (easy) command.

A substitution would certainly be more precise and generic at the same time but also more verbose:

:%s/\s\+\S\+\s\+\S\+\s\+\S\+\s*$

or:

:%s/\v\s+\S+\s+\S+\s+\S+\s*$

Or we could simply do it UNIX-style:

:%!cut -d' ' -f -4

another edit

While looking for a smarter way to use cut I stumbled on this answer which mentions an overcharged version of cut called cuts. It can be used like this:

:%!cuts -D' ' -0-3
Community
  • 1
  • 1
romainl
  • 186,200
  • 21
  • 280
  • 313
  • `$3F D` won't work if the words are separated by tabs or multiple spaces. `$3bDx` is slightly better but `$3gelD` is probably best. `$3b3daw` does the same but is longer; `$daw..` is an interesting alternative. Of course with the `:%norm` prefix. – balintpekker Jul 31 '14 at 06:17
  • 1
    @balintpekker: `$3gelD` is probably the best but doesn't account for the dash used as a minus sign. You'd want `gE`. – Michael Foukarakis Jul 31 '14 at 06:34
  • @balintpekker, my answer addresses the sample in the question, no more no less. Michael's solution is more generic but fails because of the trailing space on the first line in the given sample. Vim is not at all about finding absolute generic solutions. – romainl Jul 31 '14 at 07:10
2

add one answer of calling awk:

%!awk 'NF-=3'
Kent
  • 189,393
  • 32
  • 233
  • 301
0

You can use visual block, but this won't work if the length of the words differs too much. It will however work for the example you posted. Move to the space after 6, and press Ctrl+v. Then press $ to jump to the end of the line and move down as many lines as you want to delete.

Not the best solution, but learning to do stuff like this regularly greatly increases your productivity.

trippelganger
  • 159
  • 1
  • 8