Vim Tips Wiki
(review, merge comment, flesh out tip with more content/link)
(→‎Comments: answer question)
Tag: sourceedit
(22 intermediate revisions by 12 users not shown)
Line 3: Line 3:
 
|previous=212
 
|previous=212
 
|next=214
 
|next=214
|created=February 10, 2002
+
|created=2002
 
|complexity=basic
 
|complexity=basic
 
|author=tarjei
 
|author=tarjei
Line 9: Line 9:
 
|rating=30/33
 
|rating=30/33
 
|category1=Usage
 
|category1=Usage
  +
|category2=
 
}}
 
}}
The ex command, 'g' is very useful for acting on lines that match a pattern. You can use it with the ex command, 'd' to delete all lines that contain/do not contain a particular pattern.
+
The ex command <code>g</code> is very useful for acting on lines that match a pattern. You can use it with the <code>d</code> command, to delete all lines that contain a particular pattern, or all lines that do not contain a pattern.
   
For a trivial example, delete all lines containing "profile":
+
For example, to delete all lines containing "profile" (remove the <code>/d</code> to show the lines that the command will delete):
 
<pre>
 
<pre>
 
:g/profile/d
 
:g/profile/d
 
</pre>
 
</pre>
   
Obviously, more complex patterns can be used, such as deleting all lines that are empty or contain only whitespace:
+
More complex patterns can be used, such as deleting all lines that are empty or that contain only whitespace:
 
<pre>
 
<pre>
 
:g/^\s*$/d
 
:g/^\s*$/d
 
</pre>
 
</pre>
   
Finally, to delete all lines that do NOT contain a pattern, use g!, like this command to delete all lines that are not comment lines in a Vim script:
+
To delete all lines that do ''not'' contain a pattern, use <code>g!</code>, like this command to delete all lines that are not comment lines in a Vim script:
 
<pre>
 
<pre>
 
:g!/^\s*"/d
 
:g!/^\s*"/d
 
</pre>
 
</pre>
   
Note that the 'g!' command is equivalent to the 'v' command, so you could also do the above with:
+
Note that <code>g!</code> is equivalent to <code>v</code>, so you could also do the above with:
 
<pre>
 
<pre>
 
:v/^\s*"/d
 
:v/^\s*"/d
  +
</pre>
  +
  +
The next example shows use of <code>\|</code> ("or") to delete all lines ''except'' those that contain "<code>error</code>" or "<code>warn</code>" or "<code>fail</code>" ({{help|pattern}}):
  +
<pre>
  +
:v/error\|warn\|fail/d
 
</pre>
 
</pre>
   
 
==See also==
 
==See also==
  +
*[[VimTip72|Remove unwanted empty lines]]
*[[Filter buffer on a search result]]
+
*[[VimTip1557|Filter buffer on a search result]]
*[[Folding with Regular Expression]]
+
*[[VimTip282|Folding with Regular Expression]]
  +
*[[VimTip227|Power of g]]
   
 
==Comments==
 
==Comments==
  +
  +
Can we delete/not delete the line that precedes the search string?
  +
  +
like, in the below example i want the command to search for "keyword" and then ratain that and the line before that and deletes the test? Thank you!
  +
  +
<< file starts>>
  +
  +
this is the line that preceeds the search string
  +
  +
keyword
  +
  +
asdfgf asdfgf
  +
  +
lkjhj lkjhj
  +
  +
<< file ends>>
  +
  +
:Easy, supply a [[Range]] to the <code>d</code> command: <code>:g/keyword/-1d</code>. --[[User:Fritzophrenic|Fritzophrenic]] ([[User talk:Fritzophrenic|talk]]) 22:09, May 20, 2015 (UTC)
  +
----
  +
Can we remove all even numbered lines in a file using this feature. can we do some kind of math in the pattern. (ex: \=line(".") % 2)
  +
  +
Not really, but you can do that in two steps:
  +
<pre>
  +
:g/.*/if line('.')%2|call setline(line('.'), '===delete===')|endif
  +
:g/^==delete==$/d
  +
</pre>
  +
If you simply put delete inside the if statement all the lines will be deleted. Much faster solution is to record a macro "ddj" and play it over the file.
  +
You could delete lines from several different ranges:
  +
<pre>
  +
:let range = range(10,15)+range(20,25)+range(30,35)
  +
:g/.*/if index(range, line('.')) != -1|call setline(line('.'), '===delete===')|endif
  +
:g/^===delete===$/d
  +
</pre>
  +
But again I think the faster way to do that is to use :[range]d several times.
  +
  +
How would you instead of deleting, replace matched lines with a ''single'' newline between remaining lines?

Revision as of 22:09, 20 May 2015

Tip 213 Printable Monobook Previous Next

created 2002 · complexity basic · author tarjei · version 5.7


The ex command g is very useful for acting on lines that match a pattern. You can use it with the d command, to delete all lines that contain a particular pattern, or all lines that do not contain a pattern.

For example, to delete all lines containing "profile" (remove the /d to show the lines that the command will delete):

:g/profile/d

More complex patterns can be used, such as deleting all lines that are empty or that contain only whitespace:

:g/^\s*$/d

To delete all lines that do not contain a pattern, use g!, like this command to delete all lines that are not comment lines in a Vim script:

:g!/^\s*"/d

Note that g! is equivalent to v, so you could also do the above with:

:v/^\s*"/d

The next example shows use of \| ("or") to delete all lines except those that contain "error" or "warn" or "fail" (:help pattern):

:v/error\|warn\|fail/d

See also

Comments

Can we delete/not delete the line that precedes the search string?

like, in the below example i want the command to search for "keyword" and then ratain that and the line before that and deletes the test? Thank you!

<< file starts>>

this is the line that preceeds the search string

keyword

asdfgf asdfgf

lkjhj lkjhj

<< file ends>>

Easy, supply a Range to the d command: :g/keyword/-1d. --Fritzophrenic (talk) 22:09, May 20, 2015 (UTC)

Can we remove all even numbered lines in a file using this feature. can we do some kind of math in the pattern. (ex: \=line(".") % 2)

Not really, but you can do that in two steps:

:g/.*/if line('.')%2|call setline(line('.'), '===delete===')|endif
:g/^==delete==$/d

If you simply put delete inside the if statement all the lines will be deleted. Much faster solution is to record a macro "ddj" and play it over the file. You could delete lines from several different ranges:

:let range = range(10,15)+range(20,25)+range(30,35)
:g/.*/if index(range, line('.')) != -1|call setline(line('.'), '===delete===')|endif
:g/^===delete===$/d

But again I think the faster way to do that is to use :[range]d several times.

How would you instead of deleting, replace matched lines with a single newline between remaining lines?