Vim Tips Wiki
(Change <tt> to <code>, perhaps also minor tweak.)
(Undo revision 37152 by 67.180.48.92 (talk) What is wrong?)
(5 intermediate revisions by 5 users not shown)
Line 13: Line 13:
 
The global command <code>:g</code> is very useful. Here are some examples showing the power of <code>:g</code>.
 
The global command <code>:g</code> is very useful. Here are some examples showing the power of <code>:g</code>.
   
===Brief explanation of <code>:g</code>===
+
==Brief explanation of <code>:g</code>==
 
<pre>
 
<pre>
 
:[range]g/<pattern>/cmd
 
:[range]g/<pattern>/cmd
Line 20: Line 20:
 
This will act on the specified ''[range]'' (default whole file), by executing the Ex command ''cmd'' (An Ex command is one starting with a colon (':')) for each line matching ''<pattern>''. Before executing ''cmd'', "." is set to the current line.
 
This will act on the specified ''[range]'' (default whole file), by executing the Ex command ''cmd'' (An Ex command is one starting with a colon (':')) for each line matching ''<pattern>''. Before executing ''cmd'', "." is set to the current line.
   
===Some examples===
+
==Examples==
 
Display context (5 lines) for all occurrences of a pattern.
 
Display context (5 lines) for all occurrences of a pattern.
 
<pre>
 
<pre>
Line 33: Line 33:
 
</pre>
 
</pre>
   
Delete all lines that do NOT match a pattern.
+
Delete all lines that do '''not''' match a pattern.
 
<pre>
 
<pre>
 
:g!/<pattern>/d
 
:g!/<pattern>/d
Line 55: Line 55:
 
</pre>
 
</pre>
   
Yank all lines matching a pattern to register 'a'.
+
Move all lines matching a pattern to end of file.
 
<pre>
 
<pre>
0"ay0:g/<pattern>/y A
+
:g/<pattern>/m$
 
</pre>
 
</pre>
  +
:''Explanation'' The first <code>0</code> moves the cursor to the first character of the line. Then <code>"ay0</code> yanks into register a the motion <code>0</code>. Since the cursor is already on the first character, it yanks nothing into register a, clearing it. The <code>y A</code> is an Ex command ({{help|:y}}). It yanks the current line into register A (append to register a).
 
  +
Copy all lines matching a pattern to register 'a'.
  +
<pre>
  +
qaq:g/<pattern>/y A
  +
</pre>
 
:''Explanation'' <code>qaq</code> is a trick to clear register <code>a</code> (<code>qa</code> starts recording a macro to register <code>a</code>, then <code>q</code> stops recording, leaving <code>a</code> empty). <code>y A</code> is an Ex command ({{help|:y}}). It yanks the current line into register <code>A</code> (append to register <code>a</code>).
   
 
Increment each number at the start of a line, from the current line to end-of-file, by one (the exclamation mark in <code>:normal!</code> means this will work even if Ctrl-A has been mapped to perform a function other than its default of incrementing a number).
 
Increment each number at the start of a line, from the current line to end-of-file, by one (the exclamation mark in <code>:normal!</code> means this will work even if Ctrl-A has been mapped to perform a function other than its default of incrementing a number).
Line 94: Line 99:
 
</pre>
 
</pre>
   
===Notes===
+
==Notes==
 
Use <code>:v</code> to reVerse the sense of the search pattern. Example: Delete all lines ''not'' matching ''pattern'':
 
Use <code>:v</code> to reVerse the sense of the search pattern. Example: Delete all lines ''not'' matching ''pattern'':
 
<pre>
 
<pre>
Line 100: Line 105:
 
</pre>
 
</pre>
   
  +
----
 
Some explanation of commands commonly used with <code>:g</code>
 
Some explanation of commands commonly used with <code>:g</code>
 
<pre>
 
<pre>
Line 109: Line 115:
 
</pre>
 
</pre>
   
  +
----
Commands used with :g are Ex commands, so a help search should be
+
Since commands used with :g are Ex commands, searching for help should include the colon.
 
<pre>
 
<pre>
 
:help :<help-topic>
 
:help :<help-topic>
Line 115: Line 122:
 
</pre>
 
</pre>
   
  +
==References==
See {{help|ex-cmd-index}} for a list of Ex commands.
+
*{{help|ex-cmd-index}} provides a list of Ex commands.
  +
*{{help|10.4}} is the section of the user manual discussing the :global command.
  +
*{{help|multi-repeat}} talks about both the :g and :v commands.
   
 
==Comments==
 
==Comments==
Line 220: Line 230:
 
----
 
----
 
As always, There's More Than One Way To Do It:
 
As always, There's More Than One Way To Do It:
<pre>
+
<pre>
 
:%s/^$\n^$//g
 
:%s/^$\n^$//g
 
</pre>
 
</pre>

Revision as of 10:34, 27 January 2014

Tip 227 Printable Monobook Previous Next

created 2002 · complexity intermediate · author Arun Easi · version 6.0


The global command :g is very useful. Here are some examples showing the power of :g.

Brief explanation of :g

:[range]g/<pattern>/cmd

This will act on the specified [range] (default whole file), by executing the Ex command cmd (An Ex command is one starting with a colon (':')) for each line matching <pattern>. Before executing cmd, "." is set to the current line.

Examples

Display context (5 lines) for all occurrences of a pattern.

:g/<pattern>/z#.5
" Same, but with some beautification.
:g/<pattern>/z#.5|echo "=========="

Delete all lines matching a pattern.

:g/<pattern>/d

Delete all lines that do not match a pattern.

:g!/<pattern>/d

Delete all blank lines (^ is start of line; \s* is zero or more whitespace characters; $ is end of line)

:g/^\s*$/d

Double space the file (^ is start of line which matches each line).

:g/^/pu =\"\n\"
" Alternative (:put inserts nothing from the blackhole register)
:g/^/pu _

Copy all lines matching a pattern to end of file.

:g/<pattern>/t$

Move all lines matching a pattern to end of file.

:g/<pattern>/m$

Copy all lines matching a pattern to register 'a'.

qaq:g/<pattern>/y A
Explanation qaq is a trick to clear register a (qa starts recording a macro to register a, then q stops recording, leaving a empty). y A is an Ex command (:help :y). It yanks the current line into register A (append to register a).

Increment each number at the start of a line, from the current line to end-of-file, by one (the exclamation mark in :normal! means this will work even if Ctrl-A has been mapped to perform a function other than its default of incrementing a number).

:.,$g/^\d/exe "normal! \<C-A>"

Comment lines containing "DEBUG" statements in a C program.

" using :normal
g/^\s*DEBUG/exe "norm! I/* \<Esc>A */\<Esc>"
" using :substituting
g/^\s*DEBUG/s!.*!/* & */!

Reverse lookup for records (say an address book, with Name at start-of-line and fields after a space).

:g/<pattern>/?^\w?p "if only name is interesting
:g/<pattern>/ka|?^\w?p|'ap "if name and the lookup-line is interesting
:g/<pattern>/?^\w?|+,/^[^ ]/-1p "if entire record is interesting
Explanation See :help :range for the meaning of the constructs in the [cmd] portion of the :g commands.

Reverse a file (just to show the power of g).

:g/^/m0
Explanation According to :help multi-repeat, :g and its cousin :v work in a two-pass manner. The first pass of :g marks every line matching {pattern}, while the second pass (apparently performed starting at the file's beginning and proceeding to the end) performs the [cmd]. The above use of :g takes advantage of the order the lines are processed in (which is probably okay, though probably not technically guaranteed). It works by first marking every line, then moving the first marked line to the top of the file, then moving the second to the top of the file (above the line moved previously), then the third marked line (again above the previously moved line), and so on until the last line in the file is moved to the top, effectively reversing the file. Note that if :g processed lines in any order other than from top to bottom, this command would not work.

Add text to the end of a line that begins with a certain string.

:g/^pattern/s/$/mytext

Notes

Use :v to reVerse the sense of the search pattern. Example: Delete all lines not matching pattern:

:v/pattern/d

Some explanation of commands commonly used with :g

:2,8co15  "copy lines 2 through 8 after line 15
:4,15t$   "copy lines 4 through 15 to end of document (t == co)
:-t$      "copy previous line to end of document
:m0       "move current line to line 0 (i.e. the top of the document)
:.,+3m$-1 "current line through current+3 are moved to the lastLine-1 (i.e. next to last)

Since commands used with :g are Ex commands, searching for help should include the colon.

:help :<help-topic>
:help :k   "example

References

Comments

Over a range defined by marks a and b, operate on each line containing pattern. The operation is to replace each pattern2 with string.

:'a,'bg/pattern/s/pattern2/string/gi

Run a macro on matching lines (example assuming a macro recorded as 'q'):

:g/<pattern>/normal @q

To delete (subsequent) duplicate lines from a file:

:g/^\(.*\)\(\r\?\n\1\)\+$/d
:%!uniq

To just view the duplicates use:

/^\(.*\)\(\r\?\n\1\)\+$

Compress multiple occurrences of blank lines into a single blank line

:v/./,/./-j

Use :helpgrep '\/,\/' *.txt for an explanation.

I'll break down this incredible collapse-multiple-blank-lines command for everyone, now that I finally figured out how it works.

First, however, I'll rewrite it this way to illustrate that some of those slashes have totally different meaning than others:

:v_._,/./-1join

Note that to delimit expressions like these, just about any symbol can be used in place of the typical slashes... in this case, I used underscores. What we have is an inverse search (:v, same as :g!) for a dot ('.') which means anything except a newline. So this will match empty lines and proceed to execute [command] on each of them.

:v_._[command]

The remaining [command] is this, which is a fancy join command, abbreviated earlier as just 'j'.

,/./-1join

The comma tells it to work with a range of lines:

:help :,

With nothing before the comma, the range begins at the cursor, which is where that first blank line was. The end of the range is specified by a search, which to my knowledge actually does require slashes. The slash and dot mean to search for anything (again), which matches the nearest non-empty line and offsets by {offset} lines.

/./{offset}

The {offset} here is -1, meaning one line above. In the original command we just saw a minus sign, to which vim assumes a count of 1 by default, so it did the same thing as how I've rewritten it, but simply with one character fewer to type.

/./-1

There is a caveat about join that makes this trick possible. If you specify a range of only one line to "join", it will do nothing. For example, this command tells vim to join into one line all lines from 5 to 5, which does nothing:

:5,5join

In this case, any time you have more than one empty line (the case of interest), the join will see a range greater than one and join them together. For all single empty lines, join will leave it alone.

There's no good way use a delete command with :v/./ because you have to delete one line for every empty line you find. Join turned out to be the answer.

This command only merges truly "empty" lines... if any lines contain spaces and/or tabs, they will not be collapsed. To make sure you kill those lines, try this:

:v/^[^ \t]\+$/,/^[^ \t]\+$/-j

Or, to just clean such lines up first,

:%s/^[ \t]\+$//g

Here is a 'g' version that does the same thing as that last 'v' command

:g/^[ <TAB>]*$/,/[^ <TAB>]/-j

However, all the above blank line merging method fails to merge multiple blank lines at the end of a file. The solution is to add then remove an extra line at the end of the file. As such this is the complete blank line compressor command...

:$s/$/\\rZ/
:g/^[ <TAB>]*$/,/[^ <TAB>]/-j
:$d

Or in the form of an easy to use macro, which also tries to return to to your original place in the file.

:map QE mz:$s/$/\\rZ/<CR>:g/^[ <TAB>]*$/,/[^ <TAB>]/-j<CR>Gdd`z

As always, There's More Than One Way To Do It:

:%s/^$\n^$//g

This uses a substution (s/foo/bar/) that matches two consecutive blank lines and turns them into one. Applied globally (%), and multiple times to the same line (g), this works exactly as you'd want it to.


Another way to collapse empty lines, including whitespace, is:

:%s/^\_s\+/\r/g

\_s matches whitespace (space and tab) including end of line, \+ matches 1 or more of those, as many as possible, \r inserts carriage return specific to file format (unix-dos-mac).