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 matchingBEGIN+1— start the range one line below the match (skip the opener),/END/— search forward from the match for the next line matchingEND-1— stop one line before that closing delimiterdelete— 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
deletefors/.*//to blank lines instead of removing them - Use
d _instead ofdeleteto avoid polluting the unnamed register - Replace
BEGIN/ENDwith 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)