Many ex commands that perform normal editing operations have an
equivalent in vi that does the job more simply.
Obviously, you will use dw
or dd
to delete a single word
or line rather than using the delete
command in ex.
However, when you want to make changes that affect numerous lines, you
will find the ex commands more useful.
They allow you to modify large blocks of text with a single command.
These ex commands are listed below, along with abbreviations for those commands. Remember that in vi each ex command must be preceded with a colon. You can use the full command name or the abbreviation, whichever is easier to remember.
delete | d | Delete lines. |
move | m | Move lines. |
copy | co | Copy lines. |
t | Copy lines (a synonym for co ). |
For each ex editing command, you have to tell ex
which line number(s) to edit.
And for the ex move
and copy
commands, you also need to tell ex where to
move or copy the text to.
You can specify line addresses in several ways:
With explicit line numbers.
With symbols that help you to specify line numbers relative to your current position in the file.
With search patterns as addresses that identify the lines to be affected.
Let's look at some examples.
You can use line numbers to define explicitly a line or range of lines. Addresses that use explicit numbers are called absolute line addresses. For example:
:3,18d | Delete lines 3 through 18. |
:160,224m23 | Move lines 160 through 244 to follow line 23.
(Like |
:23,29co100 | Copy lines 23 through 29 and put after line 100.
(Like |
:set number
or its abbreviation:
:set nu
displays line numbers. The file practice then appears:
1 With a screen editor 2 you can scroll the page, 3 move the cursor, delete lines, 4 insert characters and more
The displayed line numbers are not saved when you write a file, and they do not print if you print the file. Line numbers are displayed either until you quit the vi session or until you disable the set option:
:set nonumber
or:
:set nonu
To temporarily display the line numbers for a set of lines, you can use
the #
sign.
For example:
:1,10#
would display the line numbers from line one to line ten.
As described in Chapter 3, Moving Around in a Hurry , you can also use the [CTRL-G] command to display the current line number. You can thus identify the line numbers corresponding to the start and end of a block of text by moving to the start of the block, typing [CTRL-G] then moving to the end of the block and typing [CTRL-G] again.
Yet another way to identify line numbers is with the ex
=
command:
:=
Print the total number of lines.
:.=
Print the line number of the current line.
:/
pattern
/=
Print the line number of the first line that matches pattern.
You can also use symbols for line addresses.
A dot (.
) stands for the current line;
$
stands for the
last line of the file.
%
stands for every line in the file; it's the same as the
combination 1,$
.
These symbols can also be combined with absolute line addresses.
For example:
:.,$d
Delete from current line to end of file.
:20,.m$
Move from line 20 through the current line to the end of the file.
:%d
Delete all the lines in a file.
:%t$
Copy all lines and place them at the end of the file (making a consecutive duplicate).
In addition to an absolute line address, you can specify an address relative to the current line. The symbols + and - work like arithmetic operators. When placed before a number, these symbols add or subtract the value that follow. For example:
:.,.+20d
Delete from current line through the next 20 lines.
:226,$m.-2
Move lines 226 through the end of the file to two lines above the current line.
:.,+20#
Display line numbers from the current line to 20 lines further on in the file.
In fact, you don't need to type the dot (.) when you use + or -, because the current line is the assumed starting position.
Without a number following them, + and - are equivalent to +1 and -1, respectively. [1] Similarly, ++ and -- each extend the range by an additional line, and so on. The + and - can also be used with search patterns, as shown in the next section.
[1] In a relative address, you shouldn't separate the plus or minus symbol from the number that follows it. For example,
+10
means "10 lines following," but+
10
means "11 lines following (1
+
10
)," which is probably not what you mean.
The number 0
stands for the top of the file (imaginary line 0).
0
is equivalent to 1-
,
and both allow you to move or copy lines to the very start of a file,
before the first line of existing text. For example:
:-,+t0
Copy three lines (the line above the cursor through the line below the cursor) and put them at the top of the file.
Another way that ex can address lines is by using search patterns. For example:
:/
pattern
/d
Delete the next line containing pattern.
:
/pattern
/+d
Delete the line below the next line containing pattern.
(You could also use +1
instead of +
alone.)
:
/pattern1
/,/
pattern2
/d
Delete from the first line containing pattern1 through the first line containing pattern2.
:.,/
pattern
/m23
Take text from current line (.
) through the first
line containing pattern and put after line 23.
Note that patterns are delimited by a slash both before and after.
If you make deletions by pattern with vi and ex, there is a difference in the way the two editors operate. Suppose you have in your file practice the lines:
With a screen editor you can scroll the page, move the cursor, delete lines, insert characters and more, while seeing results of your edits as you make them. |
Keystrokes | Results |
---|---|
d/while | With a screen editor you can scroll the page, move the cursor, while seeing results of your edits as you make them. |
The vi delete to pattern command deletes from the cursor up to the word while but leaves the remainder of both lines. | |
:.,/while/d | With a screen editor you can scroll the of your edits as you make them. |
The ex command deletes the entire range of addressed lines; in this case both the current line and the line containing the pattern. All lines are deleted in their entirety. |
Sometimes, using a relative line address in a command can give you unexpected results. For example, suppose the cursor is on line 1, and you want to print line 100 plus the five lines below it. If you type:
:100,+5 p
you'll get an error message saying, "First address exceeds second." The reason the command fails is that the second address is calculated relative to the current cursor position (line 1), so your command is really saying this:
:100,6 p
What you need is some way to tell the command to think of line 100 as the "current line," even though the cursor is on line 1.
ex provides such a way. When you use a semicolon instead of a comma, the first line address is recalculated as the current line. For example, the command:
:100;+5 p
prints the desired lines. The +5 is now calculated relative to line 100. A semicolon is useful with search patterns as well as absolute addresses. For example, to print the next line containing pattern, plus the 10 lines that follow it, enter the command:
:/pattern/;+10 p
You already know how to use /
(slash) in vi to search for
patterns of characters in your files.
ex has a global command, g
, that lets you search for
a pattern and display all lines containing the pattern when it finds
them.
The command :g!
does the opposite of :g
. Use
:g!
(or its synonym :v
) to search for all lines that
do not contain pattern.
You can use the global command on all lines in the file, or you can use line addresses to limit a global search to specified lines or to a range of lines.
:g/
pattern
Finds (moves to) the last occurrence of pattern in the file.
:g/
pattern
/p
Finds and displays all lines in the file containing pattern.
:g!/
pattern
/nu
Finds and displays all lines in the file that don't contain pattern; also displays line number for each line found.
:60,124g/
pattern
/p
Finds and displays any lines between lines 60 and 124 containing pattern.
As you might expect, g
can also be used for global
replacements. We'll talk about that in Chapter 6, Global Replacement .
You don't always need to type a colon to begin a new ex
command. In ex, the vertical bar (|
)
is a command separator, allowing you to
combine multiple commands from the same ex prompt (in much
the same way that a semicolon separates multiple commands at the
UNIX shell prompt). When you use the |
,
keep track of the line addresses you specify.
If one command affects the order of lines in the file,
the next command does its work using the new line positions.
For example:
:1,3d | s/thier/their/
Delete lines 1 through 3 (leaving you now on the top line of the file); then make a substitution on the current line (which was line 4 before you invoked the ex prompt).
:1,5 m 10 | g/pattern
/nu
Move lines 1 through 5 after line 10, and then display all lines (with numbers) containing pattern.
Note the use of spaces to make the commands easier to see.