/commands/vim/vim-delete-lines-matching-pattern
Vim :g/pattern/d: delete all lines matching a pattern
- tool
- Vim / Neovim
- versions
- Vim 8.x, Vim 9.x, Neovim
- os
- linux, macos, windows
In Vim, :g/pattern/d deletes every line that matches pattern, and :g!/pattern/d (or :v/pattern/d) deletes every line that does not match it. :g (global) first marks all matching lines, then runs the command after the pattern, here d (delete), on each of them. u undoes the whole operation at once.
Examples
Run in Vim's batch mode on a sample file; in the editor, type the same commands after :.
printf 'keep 1\n# comment\nkeep 2\n\nDEBUG noise\nkeep 3\n' > app.conf
cp app.conf a.conf; vim -Nu NONE -i NONE -es -c 'g/^#/d' -c 'wq' a.conf
echo '--- :g/^#/d'; cat a.conf
cp app.conf b.conf; vim -Nu NONE -i NONE -es -c 'g/^\s*$/d' -c 'wq' b.conf
echo '--- :g/^\s*$/d'; cat b.conf
cp app.conf c.conf; vim -Nu NONE -i NONE -es -c 'v/keep/d' -c 'wq' c.conf
echo '--- :v/keep/d'; cat c.conf
cp app.conf d.conf; vim -Nu NONE -i NONE -es -c 'g/\cdebug/d' -c 'wq' d.conf
echo '--- :g/\cdebug/d'; cat d.confOutput
--- :g/^#/d keep 1 keep 2 DEBUG noise keep 3 --- :g/^\s*$/d keep 1 # comment keep 2 DEBUG noise keep 3 --- :v/keep/d keep 1 keep 2 keep 3 --- :g/\cdebug/d keep 1 # comment keep 2 keep 3
Variations
| Command | Effect |
|---|---|
| :g/pattern/d | Delete lines that match |
| :g!/pattern/d or :v/pattern/d | Delete lines that do not match |
| :g/^\s*$/d | Delete empty and whitespace-only lines |
| :g/\cerror/d | Case-insensitive match (\c anywhere in the pattern) |
| :10,50g/pattern/d | Only within lines 10 to 50 |
| :g/pattern/d _ | Delete into the black hole register, keeping the unnamed register |
| :g/pattern/m$ | Move matching lines to the end of the file instead |
| :g/pattern/y A | Append matching lines to register a (clear it first with qaq) |
Patterns with slashes
Any single-byte character other than a letter, \, ", | or ! can delimit the pattern, so paths need no escaping:
:g#/usr/local#dHow :g works
:g runs in two passes. First it marks every line in the range (the whole file by default) that matches the pattern. Then it goes to each marked line in turn and runs the command with that line as the current line. Because lines are marked before anything is deleted, deleting one line does not make :g skip the next one, which is a common problem with hand-written loops. The command after the pattern can be any Ex command and can carry its own range relative to the matched line, so .,+1d deletes the matching line and the one after it:
printf 'start\nERROR disk full\n at line 3\nok\nERROR timeout\n at line 9\nend\n' > log.txt
cp log.txt a.txt; vim -Nu NONE -i NONE -es -c 'g/^ERROR/.,+1d' -c 'wq' a.txt
echo '--- :g/^ERROR/.,+1d'; cat a.txt
vim -Nu NONE -i NONE -es -c 'redir! > msg.txt' -c 'g/zzz/d' -c 'redir END' -c 'qa!' log.txt
echo '--- :g/zzz/d on a file without zzz'; tr -d '\r' < msg.txt | grep -v '^$'Output
--- :g/^ERROR/.,+1d start ok end --- :g/zzz/d on a file without zzz Pattern not found: zzz
When nothing matches, Vim prints Pattern not found: followed by the pattern and changes nothing. When more lines than the report option (default 2) are deleted, it reports the count, such as 3 fewer lines.
Pattern syntax to remember
Vim patterns are not PCRE. In the default magic mode, \| is alternation, \( \) group, \+ and \= are the one-or-more and optional quantifiers, and \{n,m} is a counted repeat. Starting the pattern with \v (very magic) makes those characters special without backslashes, closer to other regex flavours. \c makes one search case-insensitive and \C case-sensitive, regardless of ignorecase. To reuse the last search, leave the pattern empty: after /TODO, :g//d deletes every line matching TODO.
Outside Vim
For files you do not want to open, sed '/pattern/d' file and grep -v 'pattern' file give the same result from the shell; see sed delete lines matching a pattern. Inside Vim, :g keeps undo history and works on the buffer you are editing, including unsaved changes. To change the matching lines instead of deleting them, combine :g with :s, as in Vim search and replace.
FAQ
How do I undo :g/pattern/d?
Press u once in Normal mode. Vim records the whole :g command as one change, however many lines it deleted.
How do I delete lines that contain either of two words?
Use alternation in the pattern, :g/foo\|bar/d. In Vim's default magic mode the | must be escaped; with very magic, :g/\v(foo|bar)/d, it does not.
How do I delete matching lines without overwriting what I yanked?
Delete into the black hole register with :g/pattern/d _. The unnamed register and the numbered registers stay as they were.