vimtricks.wiki Concise Vim tricks, one at a time.

How do I delete all lines between two delimiter patterns without removing the delimiters themselves?

Answer

:g/BEGIN/+1,/END/-1 delete

Explanation

By combining the :global command with a relative address range, you can delete the content between repeating delimiter pairs while leaving the delimiters intact. The +1 offset skips the opening delimiter, and the -1 offset stops before the closing one.

How it works

  • :g/BEGIN/ — for each line matching BEGIN
  • +1 — start the range one line below the match (skip the opener)
  • ,/END/ — search forward from the match for the next line matching END
  • -1 — stop one line before that closing delimiter
  • delete — delete the resulting range of lines

Example

Given:

BEGIN
  line to remove
  another line
END
BEGIN
  more content
END

Running :g/BEGIN/+1,/END/-1 delete results in:

BEGIN
END
BEGIN
END

Both content blocks are removed while BEGIN and END lines are preserved.

Tips

  • Swap delete for s/.*// to blank lines instead of removing them
  • Use d _ instead of delete to avoid polluting the unnamed register
  • Replace BEGIN/END with any anchored pattern, e.g. ^### for Markdown section headers
  • Works for multiple non-nested pairs in a single pass
  • If BEGIN and END are adjacent, the range collapses and no lines are deleted (safe no-op)

Next

How do I enable matchit so % jumps between if/else/end style pairs?