So far you have learned how to repeat the last change with the dot command (`.`), to replay actions with macros (`q`), and to store texts in the registers (`"`).
By the way, you may have heard of the term "Ex Commands" before. In this guide, I refer them as command-line commands. Both Ex commands and command-line commands are the same. They are the commands that start with a colon (`:`). The substitute command in the last chapter was an example of an Ex command. They are called Ex because they originally came from the Ex text editor. I will continue to refer to them as command-line commands in this guide. For a full list of Ex commands, check out `:h ex-cmd-index`.
The `pattern` matches all lines containing that pattern, similar to the pattern in the substitute command. The `command` can be any command-line command. The global command works by executing `command` against each line that matches the `pattern`.
If you have the following expressions:
```
const one = 1;
console.log("one: ", one);
const two = 2;
console.log("two: ", two);
const three = 3;
console.log("three: ", three);
```
To remove all lines containing "console", you can run:
```
:g/console/d
```
Result:
```
const one = 1;
const two = 2;
const three = 3;
```
The global command executes the delete command (`d`) on all lines that match the "console" pattern.
When running the `g` command, Vim makes two scans across the file. On the first run, it scans each line and marks the line that matches the `/console/` pattern. Once all the matching lines are marked, it goes for the second time and executes the `d` command on the marked lines.
The global command uses the same pattern system as the substitute command, so this section will serve as a refresher. Feel free to skip to the next section or read along!
If you have these expressions:
```
const one = 1;
console.log("one: ", one);
const two = 2;
console.log("two: ", two);
const three = 3;
console.log("three: ", three);
```
To delete the lines containing either "one" or "two", run:
```
:g/one\|two/d
```
To delete the lines containing any single digits, run either:
```
:g/[0-9]/d
```
or
```
:g/\d/d
```
If you have the expression:
```
const oneMillion = 1000000;
const oneThousand = 1000;
const one = 1;
```
To match the lines containing between three to six zeroes, run:
-`:1,5g/console/d` matches the string "console" between lines 1 and 5 and deletes them.
-`:,5g/console/d` if there is no address before the comma, then it starts from the current line. It looks for the string "console" between the current line and line 5 and deletes them.
-`:3,g/console/d` if there is no address after the comma, then it ends at the current line. It looks for the string "console" between line 3 and the current line and deletes them.
-`:3g/console/d` if you only pass one address without a comma, it executes the command only on line 3. It looks on line 3 and deletes it if has the string "console".
In addition to numbers, you can also use these symbols as range:
-`.` means the current line. A range of `.,3` means between the current line and line 3.
-`$` means the last line in the file. `3,$` range means between line 3 and the last line.
-`+n` means n lines after the current line. You can use it with `.` or without. `3,+1` or `3,.+1` means between line 3 and the line after the current line.
If you don't give it any range, by default it affects the entire file. This is actually not the norm. Most of Vim's command-line commands run on only the current line if you don't pass it any range. The two notable exceptions are the global (`:g`) and the save (`:w`) commands.
-`/./` is a pattern for "non-empty lines". It matches the lines with at least one character, so it matches the lines with "const" and "console" and it does not match empty lines.
If you followed this step-by-step, you will have two semi-colons on the first line. To avoid that, run the global command on line two onward, `:2,$g/const/normal @a`.
First, `g` will look for the lines containing the pattern "console" and will find 3 matches. Then the second `g` will look for the line containing the pattern "two" from those three matches. Finally, it will delete that match.
You can change the global command's delimiter like the substitute command. The rules are the same: you can use any single byte character except for alphabets, numbers, `"`, `|`, and `\`.
To delete the lines containing "console":
```
:g@console@d
```
If you are using the substitute command with the global command, you can have two different delimiters:
```
g@one@s+const+let+g
```
Here the global command will look for all lines containing "one". The substitute command will substitute, from those matches, the string "const" with "let".
It spells *"grep"*, the same `grep` from the command line. This is **not** a coincidence. The `g/re/p` command originally came from the Ed Editor, one of the original line text editors. The `grep` command got its name from Ed.
// TODO: create a startup selling an automatic puppy feeder
```
It can be hard to keep track of all the created TODOs. Vim has a `:t` (copy) method to copy all matches to an address. To learn more about the copy method, check out `:h :copy`.
To copy all TODOs to the end of the file for easier introspection, run:
```
:g/TODO/t $
```
Result:
```
const one = 1;
console.log("one: ", one);
// TODO: feed the puppy
const two = 2;
// TODO: feed the puppy automatically
console.log("two: ", two);
const three = 3;
console.log("three: ", three);
// TODO: create a startup selling an automatic puppy feeder
// TODO: feed the puppy
// TODO: feed the puppy automatically
// TODO: create a startup selling an automatic puppy feeder
```
Now I can review all the TODOs I created, find a time to do them or delegate them to someone else, and continue to work on my next task.
// TODO: create a startup selling an automatic puppy feeder
```
## Black Hole Delete
Recall from the register chapter that deleted texts are stored inside the numbered registers (granted they are sufficiently large ). Whenever you run `:g/console/d`, Vim stores the deleted lines in the numbered registers. If you delete many lines, you can quickly fill up all the numbered registers. To avoid this, you can always use the black hole register (`"_`) to *not* store your deleted lines into the registers. Run:
Normally the global command accepts the following form: `:g/pattern/command`. However, you can also run the global command with the following form: `:g/pattern1/,/pattern2/command`. With this, Vim will apply the `command` within `pattern1` and `pattern2`.
With that in mind, let's break down the command `:g/^$/,/./-1j` according to `:g/pattern1/,/pattern2/command`:
-`/pattern1/` is `/^$/`. It represents an empty line (a line with zero character).
-`/pattern2/` is `/./` with `-1` line modifier. `/./` represents a non-empty line (a line with at least one character). The `-1` means the line above that.
-`command` is `j`, the join command (`:j`). In this context, this global command joins all the given lines.
You can sort them by running `:sort`. If you give it a range, it will sort only the lines within that range. For example, `:3,5sort` only sorts lines three and five.
The global command executes the command-line command against all matching lines. With it, you only need to run a command once and Vim will do the rest for you. To become proficient at the global command, two things are required: a good vocabulary of command-line commands and a knowledge of regular expressions. As you spend more time using Vim, you will naturally learn more command-line commands. A regular expression knowledge will require a more active approach. But once you become comfortable with regular expressions, you will be ahead of many.
Some of the examples here are complicated. Do not be intimidated. Really take your time to understand them. Learn to read the patterns. Do not give up.
Whenever you need to run multiple commands, pause and see if you can use the `g` command. Identify the best command for the job and write a pattern to target as many things at once.