Reputation: 531
I'm reviewing some logs with Java exception spam. The spam is getting is making it hard to see the other errors.
Is is possible in vim to select a block of text, using visual mode. Delete that block every place it occurs in the file.
If vim can't do it, I know silly question, vim can do everything. What other Unix tools might do it?
Upvotes: 3
Views: 751
Reputation: 5112
Based on our discussion in the comments, I guess a "block" means several complete lines. If the first and last lines are distinctive, then the method you gave in the comments should work. (By "distinctive" I mean that there is no danger that these lines occur anywhere else in your log file.)
For simplifications, I would use "ay$
to yank the first line into register a
and "by$
to yank the last line into register b
instead of using Visual mode. (I was going to suggest "ayy
and "byy
, but that wold capture the newlines)
To be on the safe side, I would anchor the patterns: /^{text}$/
just in case the log file contains a line like "Note that {text} marks the start of the Java exception." On the command line, I would use <C-R>a
and <C-R>b
to paste in the contents of the two registers, as you suggested.
:g/^<C-R>a$/,/^<C-R>b$/d
What if the yanked text includes characters with special meaning for search patterns? To be on the really safe side, I would use the \V
(very non-magic) modifier and escape any slashes and backslashes:
:g/\V\^<C-R>=escape(@a, '/\')<CR>\$/,/\V\^<C-R>=escape(@b, '/\')<CR>\$/d
Note that <C-R>=
puts you on a fresh command line, and you return to the main one with <CR>
.
It is too bad that \V
was not available when matchit was written. It has to deal with text from the buffer in a search pattern, much like this.
Upvotes: 1
Reputation: 5746
To delete all matching lines:
:g/regex/d
To only delete the matches themselves:
:%s/regex//g
In either case, you can copy the visual selection to the command line by yanking it and then inserting it with <C-r>"
. For example, if your cursor (|
) is positioned as follows:
hello wo|rld
Then you can select world
with viw
, yank the selection with y
, and then :g/<C-r>"/d
.
To delete all matching lines:
$ sed '/regex/d' file
To only delete the matches themselves:
$ sed 's/regex//g' file
To delete all matching lines:
$ grep -v 'regex' file
grep only operates line-wise, so it's not possible to only delete matches within lines.
Upvotes: 2
Reputation: 45087
Sounds like you are looking for the :global
command
:g/pattern/d
The :global
command takes the form :g/{pat}/{cmd}
. Read it as: run command, {cmd}
, on every line matching pattern, {pat}
.
You can even supply a range to the :delete
(:d
for short) command. examples:
:,+3d
:,/end_pattern/d
Put this togehter with the :global
command and you can accomplish a bunch. e.g. :g/pat/,/end_pat/d
For more help see:
:h :g
:h :d
:h :range
Upvotes: 3