sponsor Vim development Vim logo Vim Book Ad

intermediate Tip #227: Power of :g

 tip karma   Rating 408/159, Viewed by 12039 

created:   March 24, 2002 3:15      complexity:   intermediate
author:   Arun Easi      as of Vim:   5.7

:g is something very old and which is very powerful. I just wanted to illustrate the use of it
with some examples. Hope, it will be useful for someone.

Brief explanation for ":g"
-------------------------
Syntax is:
    :[range]:g/<pattern>/[cmd]
You can think the working as, for the range (default whole file), execute
the colon command(ex) "cmd" for the lines matching <pattern>. Also, for all
lines that matched the pattern, "." is set to that particular line (for
certain commands if line is not specified "." (current line) is assumed).

Some examples
-------------
Display context (5 lines) for all occurences of a pattern
    :g/<pattern>/z#.5
    :g/<pattern>/z#.5|echo "=========="
    << same as first, but with some beautification >>
Delete all lines matching a pattern
    :g/<pattern>/d
Delete all blank lines (just an example for above)
    :g/^\s*$/d
Double space the file
    :g/^/pu =\"\n\"
    :g/^/pu _
    << the above one also works >>
Copy all lines matching a pattern to end of file
    :g/<pattern>/t$
Yank all lines matching a pattern to register 'a'
    0"ay0:g/<pattern>/y A
Increment the number items from current line to end-of-document by one
    :.,$g/^\d/exe "normal! \<c-a>"
Comment (C) lines containing "DEBUG" statements
    g/^\s*DEBUG/exe "norm! I/* \<Esc>A */\<Esc>"
A Reverse lookup for records
(eg: An address book, with Name on start-of-line and fields after a space)
    :g/<patern>?^\w?p               "if only name is interested
    :g/<patern>/ka|?^\w?p|'ap       "if name and the lookup-line is interested
    :g/<patern>/?^\w?|+,/^[^ ]/-1p  "if entire record is interested
Reverse a file (just to show the power of 'g')
    :g/^/m0

Foot note 1: use :v to negate the search pattern
Foot note 2: Some explanation of commonly used commands with :g
:2,8co15 => Copy lines 2 through 8 after line 15
:4,15t$  => Copy linesa 4 through 15 towards end of document (t == co)
    :-t$  => Copy previous line to end of document
     :m0  => Move current line to the top of the document
:.,+3m$-1 => Move current line through cur-line+3 to the last but one line
             of the document
Foot note 3: Commands used with :g are ex commands, so a help search should
             be,
                :help :<help-topic>
                eg. :help :k

 rate this tip  Life Changing Helpful Unfulfilling 

<<Edit file under cursor after a horizontal split | Deleting nested reply threads in emails >>

Additional Notes

[email protected], March 28, 2002 7:10
Thanx Karma for extending my g// knowledge

Here's a very useful g// for day to day use

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

zzapper
Hal Atherton, April 23, 2002 10:12
g WITH CONFIRM c

Here's something very curious:

:%s/foo/bar/gc
is of course a substitution effective for the entire file
with confirm on each occurrence of "foo"
with the option of quitting at any point.

However, using something similar,

:g/foo/s//bar/gc
using the global g to effect the entire file --
does NOT allow quitting at any point
(even with the use of <ESC>).

If there are hundreds of "foo" -- it's an important fine point...

Invite further comments...
Arun Easi, April 23, 2002 23:33
g/foo/s//bar/gc => run the command s//bar/gc for each of the line
matching foo. It is like running multiple "s//" commands (Hence
you have to press q for each of the invocation). The
g in "s///gc" does not imply entire file, it just implies all occurence
on a line (or else, it would have substituted only the first)
[email protected], May 30, 2002 9:04
Here is one that deletes every other line (adjusting double spaced files):

:g/.*/norm jdd
pagaltzis()gmx_de, August 6, 2002 15:12
This can be done much simpler:

:%norm jdd
[email protected], February 10, 2003 4:49
Another cool g feature is to count the number of lines matching /regexp/

let x=0 | g/regexp/let x=x+1
echo x

Great, if you are editing data files.

Regards
Mike
[email protected], March 27, 2003 2:14
Reverse all the lines in a file:

:g/^/m0

I have found that useful . . . honest!

PK
[email protected], September 3, 2003 5:06
Can I do something like this using ":g" (or anything else)

I have a file which contains following kind of lines

abc123=1,2,3
bcd123=100,200,300
abcb123=1,3,4

I want to convert this to following

abc123=1,abc,2,abc,3,abc
bcd123=100,bcd,200,bcd,300,bcd
abcb123=1,abcb,3,abcb,4,abcb

Basically I want to replace each comma in a line with first few letters, which are coming before 123, of that line surrounded by 2 commas.
Anonymous, September 3, 2003 12:45
To answer  kkgahlot's question:

global // execute "s/\\([=,][^,]*\\)/\\1, " . matchstr (getline ("."), "^.\\{-}\\(123\\)\\@=") . "/g"


To make the whole thing a little more transparent some explanations (from the inside out):

We want to execute on each line a command like

s/\([=,][^,]*\)/\1, abc/g

for each line, but abc gets changed on each line.

The function

matchstr (getline ("."), "^.\\{-}\\(123\\)\\@=")

returns the string that matches the pattern /^.\{-}\(123)\@=/ on the current line. In the given examples this is the text preceding 123= at the beginning of the line. Depending on the actual requierements, a simpler expression like /^[a-z]*/ could work too.

The command

execute "s/\\([=,][^,]*\\)/\\1, " . matchstr (getline ("."), "^.\\{-}\\(123\\)\\@=") . "/g"

assembles the desired substitute command for the current line by joining some static text with the return value of the matchstr function and then executes it.

As execute works only on the current line, the command

global // execute ...

applies it to all line. If only certain lines should be proecessed replace // with some other pattern.

[email protected], November 21, 2003 10:39
Reverting lines in a file can also be done via
:%!tac

instead of tac, you can also use sort, xxd, xxd -r, cut, your-own-filter
Anonymous, March 29, 2004 7:18
too bad :g does not have a /c parameter for confirmed execution of ex commands. Something like the /c used in :<range>s/<PAT>/<REPL>/c for replacing only confirmed pattern locations.

or does it ??
[email protected], April 14, 2004 10:06
I just want to add that the :g command in vi/ed is the basis for the name for the Unix grep command, i.e. Global Regular Expression Print.  The "Print" part described the default behaviour of :g when no command was given.  Obviously this behaviour was more useful when using ed.
[email protected], August 16, 2004 23:55
Thank you for the tip
If you have questions or remarks about this site, visit the vimonline development pages. Please use this site responsibly.
Questions about Vim should go to [email protected] after searching the archive. Help Bram help Uganda.
Sponsored by Web Concept Group Inc. SourceForge Logo