Step 5 of 10

19. The Global Command

Chaining global commands

Global commands can be chained in Vim. That means the Ex command you pass to a :global invocation can be another :global invocation. This sounds a bit crazy, but think about the following examples:

  • :g/test/g/run — prints all of the lines matching both test and run
  • :g/foo/v/bar — prints all lines containing foo, but not bar
  • :g/foo/v/bar/g/baz — prints all lines containing foo and baz, but not bar

To give you some ideas, I’ve used this in the past to:

  • delete all debugging print statements that I’ve not explicitly marked with the string KEEPME (hint: :g/print/v/KEEPME/d)
  • list all of the type definitions in a file that don’t contain GET in their name (hint: :g/^type/v/GET/)
  • slowly whittle down what I’m grepping for in a file by chaining more global commands — I think this is a bit easier to cognitively manage than writing a more complex regex

The only limitation with using the global command recursively is that you can only specify a range for the first invocation of :global. As in, you can’t do this:

:g/foo/-10,+10g/bar/d

Thankfully the situations where you’d ever need this are extremely rare.

Let’s give this a try in the editor. The chain reads left to right: :g/foo selects the lines containing foo, v/bar filters that selection down to the ones without bar, and d deletes what’s left. Work through the checklist below to run it.

  1. Delete the foo-but-not-bar lines with :g/foo/v/bar/d Type :g/foo/v/bar/d and hit Enter — every survivor will either have no foo, or a bar keeping it safe.
Delete the foo-but-not-bar lines with :g/foo/v/bar/d Type :g/foo/v/bar/d and hit Enter — every survivor will either have no foo, or a bar keeping it safe.

Last one — goal check runs when it's done

Loading editor…