91

In vim, I often need to delete, or yank/put large blocks of text.

I can count the lines of text and enter something like 50dd to delete 50 lines.

But that's a bit of a pain. How can I delete this large block of text without having to know how many lines to delete in advance?

  • 4
    How do you know where the end is? If you can describe the end you can delete to that point. If you can describe how you can move to the end. Then deleting to the end is no different than moving to the end. – Martin York Feb 22 '15 at 9:40
  • @Loki, moving to the end is usually just using page-down and the arrow keys until I reach there. It may be the first or tenth blank line, it may be the first closing brace. Bottom line is, it varies quite a bit. – user579 Feb 22 '15 at 13:31
  • 2
    also check this answer: stackoverflow.com/a/16407391/164835 – Kent Jun 8 '15 at 13:08

15 Answers 15

112

Go to the starting line of your block, and type ma (mark "a", though you can of course use different letters, and even multiple letters for different marks provided you can keep it straight in your head what each letter is a mark of).

Then go to the last line and enter d'a (delete to mark "a") or y'a (yank to mark "a") (a).

That will delete/yank all lines from the current to the marked one (inclusive).

Then you can paste it somewhere else with the normal paste commands, such as p or P.

It's also compatible with vi as well as vim, on the off chance that your environment is not blessed with the latter.


(a) I also use this to save my place in the file if I have to go looking elsewhere for something like, for example, copy-pasting the definition of a function I want to call.

I simply mark the current line in the same way, ma, then wander off to find whatever you're looking for.

Then, once I've found it and copied it to a register, I just enter 'a to go back to mark "a", the line I saved beforehand, where I can then paste it.

  • 9
    Might as well use visual mode for this, right? – jmc Feb 19 '15 at 8:14
  • 3
    That's one way, jmc, but I'm not sure standard vi has a visual mode. – user579 Feb 19 '15 at 8:52
  • 5
    Since I moved from visual selection to marking and relative line numbers about a year ago I found that vi motion commands are much faster and efficient then visual selection. Even though the later is easier every time I hit the v key I ask myself do I really need it or is there a better motion way? – Sukima Feb 19 '15 at 14:21
  • 1
    Yeah, in the same way it's interesting, @Sukima, that I feel more efficient the less I use the mouse, even in a GUI. I find myself being faster if I can stay on the keyboard. – user579 Feb 19 '15 at 21:14
  • 3
    If you're ever editing something with really long lines, the backtick version of this might come in very handy as well (which refers to the place withinin the line, rather than the whole line). – msouth Feb 20 '15 at 7:31
65

In Vim, use visual line mode:

  1. Put your cursor on the top line of the block of text/code to remove
  2. Press V (That's capital "V" : Shift + v )
  3. Move your cursor down to the bottom of the block of text/code to remove
  4. Press d

For deleting large blocks of text this is preferred over simple visual mode because you don't need to worry about which column the cursor is at.

  • 3
    In step 3. you can move faster using object motions. For example can use } to select entire paragraph or ) for sentences. There are more, you can read about them in :h object-motions – mxlian May 14 '15 at 18:55
  • 2
    Also searching for a substring with /something<CR> is a very efficient method to reach to the end of your selection block – mxlian May 14 '15 at 18:59
  • 1
    This is my preferred method. However alternatively without having to repeatedly press j to move the cursor down (step 3), you can type the line number followed by G to select until that line. Example: V150Gd – Ranhiru Jude Cooray Mar 5 '16 at 16:08
42

You can :set relativenumber, so you don't have to count. ;)

  • 8
    Or :set number, and then use d35G to delete until line 35. – Random832 Feb 20 '15 at 16:22
  • 2
    The numbers.vim plugin recommended in ediblemanager's answer is like relativenumber, but better :-) – Martin Tournoij Feb 25 '15 at 12:54
39

You can easy delete large block of text knowing its structure.

If it's paragraph, use: d{ (e.g. you can prefix with number of paragraphs)

If it's block of code within parenthesis, use: d%

If the text appearing till end of the file, use: dG

If you know how it ends, use: d/ and type ending text followed by Enter (you can also use regular expression, so the possibilities are endless).

Alternatively use visual mode (V) and use motion keys to quickly select the text (e.g. by {) and remove it (d).

Or as Lie Ryan suggested, use d/search-string/e to delete text from current cursor to searched string.

See: :help d and :help motion for more info.

  • 2
    There is also d/search-string/e to delete from current cursor to the end of the search string including the search string itself and c/search-query to get into insert mode after deletion. Using d/ with set incsearch is a neat combination as it allows you to interactively figure out whether you are operating on the right text range, and help you know when to stop typing the search query to avoid typing more than is necessary. – Lie Ryan Feb 20 '15 at 15:17
  • 4
    I also find d with a (outer), or i (inner) and an object specifier very useful. Objects such as w for word, p for paragraph, ( or b for (...), [ for [...], { or B for {...} etc. documentation for visual-operators. – Shahbaz Feb 23 '15 at 15:13
22

You can use motions and/or text objects. For instance, you can delete everything from the cursor to the next blank line with d}. If the cursor is inside a paragraph, the paragraph may be deleted with dip or dap. If the cursor is within a HTML tag, you can delete it with dit or dat.

Good mnemonics for these are "delete inside" and "delete around" (paragraph / tag / parenthesis).

11

I usually do

:<start>,<end>d

which will delete every line between the start and end line numbers provided (including the given lines).

Note that both start and end can be absolute line numbers, patterns, or offsets from another position.

Also see doubleDown's comment about viewing Vim's range documentation, it has some useful tips.

Example:

Say you have the following file:

1. The quick brown
2. fox jumps
3. over the
4. lazy dog.

Then by using the command :2,3d or :/fox/,/over/d or :/quick/+1,/lazy/-1 or :+1,+2d if you're on the first line or :-1,.d if you're on the third line, you end up with:

1. The quick brown
4. lazy dog.
  • But this means you still need to count the lines? Or did I misunderstand your answer? – Martin Tournoij Feb 19 '15 at 10:51
  • 7
    You don't need to count the lines, but you do need to know the line numbers. – jmc Feb 19 '15 at 10:55
  • First do :set ruler, then go to the top & bottom of the text to find start and end line numbers, then do :<start>,<end>d – roblogic Feb 20 '15 at 6:46
  • 1
    You could also use relative line numbers :+12,+24d – rpattabi Mar 22 '15 at 6:39
  • 2
    Actually, you can use a pair of line numbers, a pair of patterns, or mixed pair for <start> and <end> for this. For reference, see :h [range]. So it's actually quite a bit more flexible than you made it out to be. – doubleDown Oct 27 '15 at 12:21
5

If it is delimited blocks (eg: code or XML/HTML tags) that you're dealing with, you can position the cursor at the start of the block and use the visual mode along with % to quickly select entire blocks of code and then hit d to delete them.

  • 5
    Alternatively, you can use dap to delete a paragraph, da(, da{, da[, to delete blocks delimeted by parentheses, braces, or square brackets. For html there is dat, which deletes a tag, and da' and da" delete strings. There is also the dip, di(, etc variants, that will delete everything inside the delimiters, but leave the delimiters intact. Alternatively, you can use vap (resp vip) to select all (resp inner) paragraph. (And so there is va( and vi(.) Further there is cap and cip (or ca( and ci() to delete and go to insert mode (i.e., "change"). And yap to yank – jmc Feb 19 '15 at 8:12
  • I think some of the bindings @jmc described in his earlier comment are from the surround.vim plugin by Tim Pope. It's a great plugin that I'd recommend installing, but it does mean these bindings aren't part of the default vim installation. – Haegin Oct 2 '17 at 18:33
5

Apart from all the other good advice I'm adding d+Shift+L for deleting everything from the current cursor position to the last visible line on the screen. Repeating the command will get you down relatively fast.

5

The numbers.vim plugin is very useful for this. It's an enhanced way to precede each line with a line number. Like 'number' and 'relativenumber', both roled into one!

It's enabled by default after installation, you also want to add set number to your vimrc if you haven't got it already, since it behaves in strange ways if you don't have it.

In normal mode it looks similar to :set relativenumber:

  3 call plug#begin('~/.vim/plugged')
  2 
  1 Plug 'myusuf3/numbers.vim'
7   set number█
  1 
  2 " Add indentation 'guidelines' (:IndentLinesToggle or <F11>)
  3 Plug 'Yggdroot/indentLine'

It shows you relative line numbers, except for the line where the cursor is on, where it shows the absolute line number (7 in this case).

If we then switch to insert mode, it will behave as if number was set by always showing absolute line numbers:

  4 call plug#begin('~/.vim/plugged')
  5 
  6 Plug 'myusuf3/numbers.vim'
  7 set number█
  8   
  9 " Add indentation 'guidelines' (:IndentLinesToggle or <F11>)
 10 Plug 'Yggdroot/indentLine'

There are some more options and a few commands (check the homepage), but the defaults should work for most people.

  • At first I thought this answer was a bit off topic but then I installed the plugin and I have to say it's a game changer for me. I used to swap manually and the extra mental step meant that I shyed away from using those motions. Thank you! – Sukima Feb 19 '15 at 15:16
  • 1
    This sounds like something that one InsertEnter/InsertLeave autocmd to toggle relative line numbering could do. Am I missing something? – Ben Feb 27 '15 at 1:16
  • I'm VERY late to the party but @Ben is right, this is just a couple autocommand lines. For example, in my vimrc I have set number, set relativenumber then autocmd InsertEnter * :set norelativenumber and autocmd InsertLeave * :set relativenumber – B Layer Apr 17 '18 at 3:53
4

Another approach is if you are trying to delete to a specific pattern, you can simply type d/delimEnter.

2

You can use the normal procedure of entering d plus a motion (as already explained in the other answers). The EasyMotion plugin, provides new motions you can use that could solve your problem in a quick and easy way.

Say you want to to delete from the current cursor position to the end of any given word on the screen, the motion keys would be <Leader><Leader>e (akin to the normal e motion). Then type the highlighted letter(s) that appear at the end of the word in question. There is also a line motion so you can delete the current line down to the line in question with <Leader><Leader>j.

I have my <Leader> key set to ,. So, the full command is d<Leader><Leader>e{highlighted letter(s)}.

From :help easymotion:

EasyMotion provides a much simpler way to use some motions in vim. It takes the <number> out of <number>w or <number>f{char} by highlighting all possible choices and allowing you to press one key to jump directly to the target.

When one of the available motions is triggered, all visible text preceding or following the cursor is faded, and motion targets are highlighted.

Edit:

EasyMotion's github repository is at https://github.com/Lokaltog/vim-easymotion.

This reddit about people using easymotion might be a fun read.

1

There is a simple solution that can solve your problem.

Place your cursor at the begining of the text block you want to remove, and do d50gg.

This will delete all the lines from your current position to the 50th line of your text.

e.q: if your cursor is at line 46, d50gg will delete 4 lines.

  • 1
    I'd suggest using G instead of gg as it also works in vi, and of course :set number is always useful for finding what line number the line you want to go to is. – Random832 Feb 20 '15 at 16:24
  • The whole point of this question is that you don't know how many lines you want to remove. – 200_success Feb 20 '15 at 17:30
  • 200_success, you don't have to know how many lines you want to remove with the answer i posted. All you have to know is "to which line do you want to remove" – Geee Feb 20 '15 at 18:15
1

Use visual mode with line highlighting.

  1. Put your cursor on the top line of the block of text/code to remove
  2. Press Shift + v
  3. Move your cursor down to the bottom of the block of text/code to remove
  4. Press d

I prefer this method for deleting blocks of code because it deletes whole lines compared to simply using visual mode where you have to position the cursor in the right column to delete what you want.

1

I don't like to have relativenumber on all the time, so I configured my Vim to enable it only when I am in Visual Mode:

" Entering Visual mode
nnoremap <silent>     v :set relativenumber cursorcolumn<CR>v
nnoremap <silent> <C-q> :set relativenumber cursorcolumn<CR><C-q>
nnoremap <silent>    gv :set relativenumber cursorcolumn<CR>gv
nnoremap <silent>     V :set relativenumber<CR>V

" When finished
augroup ClearCursorColumnAndLine
    autocmd!
    autocmd CursorHold * set norelativenumber nocursorcolumn nocursorline
augroup END

This makes your task easy:

V49jd

because after hitting V you can see how far away the target line is.

This may prove annoying in the long run (the text shifts right and left when relativenumber is enabled/disabled), but so far I am quite enjoying it.

  • 1
    I think you use v<Esc>d50j? – Martin Tournoij Feb 26 '15 at 11:59
  • Thanks, I had indeed written it incorrectly. Actually I start with V if I know I will be doing a line-wise operation, and then I can leave the d until last, for greater confidence. – joeytwiddle Feb 26 '15 at 16:18
  • My answer appears to be a poor man's approximation of the numbers.vim plugin offered in another answer. ;-) – joeytwiddle Mar 1 '15 at 7:57
1

What worked great for me with vi:

  1. :set number to view the number of the line until where I wanted to delete;

    +1289 idle 
    +1289 idle 
    +1290 # <- I want to delete until here
    +1291 if [[ ! -z "$SFIN" ]]
    
  2. Go back to the line where deletion had to start

  3. Used deletion from current line, in normal mode> d1290G

Your Answer

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